<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>脚手架-RuoYi-Cloud 微服务版 | 浪飞IT小栈</title>
    <meta name="generator" content="VuePress 1.9.9">
    <link rel="icon" href="/img/favicon.ico">
    <meta name="description" content="前后端技术分享">
    <meta name="keywords" content="前端博客,后端博客,人工智能,个人技术博客,前端,前端开发,前端框架,web前端,前端面试题,技术文档,学习,面试,JavaScript,js,ES6,TypeScript,vue,python,css3,html5,Node,git,github,markdown,java,Spring,Springboot,Redis,mysql">
    <meta name="baidu-site-verification" content="7F55weZDDc">
    <meta name="theme-color" content="#11a8cd">
    
    <link rel="preload" href="/assets/css/0.styles.ada71c49.css" as="style"><link rel="preload" href="/assets/js/app.a2a00aa5.js" as="script"><link rel="preload" href="/assets/js/2.256f807a.js" as="script"><link rel="preload" href="/assets/js/66.799f2eb4.js" as="script"><link rel="prefetch" href="/assets/js/10.ab144fe3.js"><link rel="prefetch" href="/assets/js/11.062e0879.js"><link rel="prefetch" href="/assets/js/12.f9c60882.js"><link rel="prefetch" href="/assets/js/13.0a6ebfcf.js"><link rel="prefetch" href="/assets/js/14.03fc6f12.js"><link rel="prefetch" href="/assets/js/15.19dbf9fd.js"><link rel="prefetch" href="/assets/js/16.6e68160b.js"><link rel="prefetch" href="/assets/js/17.1d678834.js"><link rel="prefetch" href="/assets/js/18.4536fd5c.js"><link rel="prefetch" href="/assets/js/19.9c1b65df.js"><link rel="prefetch" href="/assets/js/20.c5f96e71.js"><link rel="prefetch" href="/assets/js/21.3f0b334e.js"><link rel="prefetch" href="/assets/js/22.55c868be.js"><link rel="prefetch" href="/assets/js/23.91286241.js"><link rel="prefetch" href="/assets/js/24.c1af1909.js"><link rel="prefetch" href="/assets/js/25.a995a755.js"><link rel="prefetch" href="/assets/js/26.abc5dea3.js"><link rel="prefetch" href="/assets/js/27.1eb62850.js"><link rel="prefetch" href="/assets/js/28.b383a871.js"><link rel="prefetch" href="/assets/js/29.088e0d73.js"><link rel="prefetch" href="/assets/js/3.cd716564.js"><link rel="prefetch" href="/assets/js/30.3ccc98d5.js"><link rel="prefetch" href="/assets/js/31.aab7cc23.js"><link rel="prefetch" href="/assets/js/32.5e16b7e6.js"><link rel="prefetch" href="/assets/js/33.4aaeb741.js"><link rel="prefetch" href="/assets/js/34.45e8e898.js"><link rel="prefetch" href="/assets/js/35.5899c97a.js"><link rel="prefetch" href="/assets/js/36.32e2e263.js"><link rel="prefetch" href="/assets/js/37.c4e27bbd.js"><link rel="prefetch" href="/assets/js/38.fe5e60d2.js"><link rel="prefetch" href="/assets/js/39.2cb0b4ee.js"><link rel="prefetch" href="/assets/js/4.edf4d5e7.js"><link rel="prefetch" href="/assets/js/40.08d5bead.js"><link rel="prefetch" href="/assets/js/41.2f80f24b.js"><link rel="prefetch" href="/assets/js/42.43a49913.js"><link rel="prefetch" href="/assets/js/43.08da7ec2.js"><link rel="prefetch" href="/assets/js/44.7c7cb8a9.js"><link rel="prefetch" href="/assets/js/45.0ddf7e7f.js"><link rel="prefetch" href="/assets/js/46.7c4609a5.js"><link rel="prefetch" href="/assets/js/47.edf3ddf8.js"><link rel="prefetch" href="/assets/js/48.569a90b9.js"><link rel="prefetch" href="/assets/js/49.fa368ac8.js"><link rel="prefetch" href="/assets/js/5.24054156.js"><link rel="prefetch" href="/assets/js/50.b9b3ea7f.js"><link rel="prefetch" href="/assets/js/51.a2ebf0fe.js"><link rel="prefetch" href="/assets/js/52.31f02238.js"><link rel="prefetch" href="/assets/js/53.4110ef1e.js"><link rel="prefetch" href="/assets/js/54.dab741c7.js"><link rel="prefetch" href="/assets/js/55.f27984e9.js"><link rel="prefetch" href="/assets/js/56.bd4c1a8e.js"><link rel="prefetch" href="/assets/js/57.375d40cb.js"><link rel="prefetch" href="/assets/js/58.932e3864.js"><link rel="prefetch" href="/assets/js/59.e657be1b.js"><link rel="prefetch" href="/assets/js/6.b259c061.js"><link rel="prefetch" href="/assets/js/60.88d94274.js"><link rel="prefetch" href="/assets/js/61.fa71d884.js"><link rel="prefetch" href="/assets/js/62.a9d3b3b7.js"><link rel="prefetch" href="/assets/js/63.f849fe75.js"><link rel="prefetch" href="/assets/js/64.1770f7a9.js"><link rel="prefetch" href="/assets/js/65.6afc33db.js"><link rel="prefetch" href="/assets/js/67.f36b2f7d.js"><link rel="prefetch" href="/assets/js/68.868cd00b.js"><link rel="prefetch" href="/assets/js/69.4c29b907.js"><link rel="prefetch" href="/assets/js/7.e34ea00f.js"><link rel="prefetch" href="/assets/js/70.1b993ed4.js"><link rel="prefetch" href="/assets/js/71.e16ad4f9.js"><link rel="prefetch" href="/assets/js/72.627505e6.js"><link rel="prefetch" href="/assets/js/73.32768e14.js"><link rel="prefetch" href="/assets/js/74.968a580d.js"><link rel="prefetch" href="/assets/js/75.42d5af3d.js"><link rel="prefetch" href="/assets/js/76.19a69d31.js"><link rel="prefetch" href="/assets/js/77.cf627a78.js"><link rel="prefetch" href="/assets/js/78.07177880.js"><link rel="prefetch" href="/assets/js/8.c4dd00ce.js"><link rel="prefetch" href="/assets/js/9.0ff73be2.js">
    <link rel="stylesheet" href="/assets/css/0.styles.ada71c49.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/logo.png" alt="浪飞IT小栈" class="logo"> <span class="site-name can-hide">浪飞IT小栈</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/pages/6138ae/" class="nav-link">Java速通</a></div><div class="nav-item"><a href="/pages/705b35/" class="nav-link">面试经典</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="精品项目" class="dropdown-title"><a href="/project/" class="link-title">精品项目</a> <span class="title" style="display:none;">精品项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>桌面端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/pages/8143cc480faf9a11/" class="nav-link">JavaScript</a></li></ul></li><li class="dropdown-item"><h4>PC后端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/note/javascript/" class="nav-link">项目1</a></li><li class="dropdown-subitem"><a href="/note/typescript-axios/" class="nav-link">项目二</a></li></ul></li></ul></div></div><div class="nav-item"><a href="/about/" class="nav-link">电子书</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/pages/0c07b2/" class="nav-link">IT杂货铺</a></div><div class="nav-item"><a href="/archives/" class="nav-link">更多资源</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><div class="blogger"><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/avatar.jpg"> <div class="blogger-info"><h3>浪飞yes</h3> <span>无法简单的人儿~</span></div></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/pages/6138ae/" class="nav-link">Java速通</a></div><div class="nav-item"><a href="/pages/705b35/" class="nav-link">面试经典</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="精品项目" class="dropdown-title"><a href="/project/" class="link-title">精品项目</a> <span class="title" style="display:none;">精品项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>桌面端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/pages/8143cc480faf9a11/" class="nav-link">JavaScript</a></li></ul></li><li class="dropdown-item"><h4>PC后端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/note/javascript/" class="nav-link">项目1</a></li><li class="dropdown-subitem"><a href="/note/typescript-axios/" class="nav-link">项目二</a></li></ul></li></ul></div></div><div class="nav-item"><a href="/about/" class="nav-link">电子书</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/pages/0c07b2/" class="nav-link">IT杂货铺</a></div><div class="nav-item"><a href="/archives/" class="nav-link">更多资源</a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>开篇</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>基础语法</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>面向对象</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>常用类</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>基础高级</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>数据库</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>前端技术</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>热门框架</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>前后端分离</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>权限控制</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>NoSQL</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>微服务</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>消息中间件</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>脚手架</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/pages/e4621d/" class="sidebar-link">脚手架-RuoYi-Vue 前后端分离版</a></li><li><a href="/pages/eed55d/" aria-current="page" class="active sidebar-link">脚手架-RuoYi-Cloud 微服务版</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#一、今日学习内容与目标" class="sidebar-link">一、今日学习内容与目标</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_1-1-前置知识点" class="sidebar-link">1.1 前置知识点</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_1-2-教学目标" class="sidebar-link">1.2 教学目标</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#二、框架介绍" class="sidebar-link">二、框架介绍</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_2-1-简介" class="sidebar-link">2.1 简介</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_2-2-内置功能" class="sidebar-link">2.2 内置功能</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_2-3-主要特性" class="sidebar-link">2.3 主要特性</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_2-4-演示地址" class="sidebar-link">2.4 演示地址</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_2-5-分类" class="sidebar-link">2.5 分类</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_2-5-1-传统版" class="sidebar-link">2.5.1 传统版</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-1-1-源码地址" class="sidebar-link">2.5.1.1 源码地址</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-1-2-在线文档" class="sidebar-link">2.5.1.2 在线文档</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-1-3-技术选型" class="sidebar-link">2.5.1.3 技术选型</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-1-4-代码结构" class="sidebar-link">2.5.1.4 代码结构</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_2-5-2-前后端分离版本" class="sidebar-link">2.5.2 前后端分离版本</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-2-1-源码地址" class="sidebar-link">2.5.2.1 源码地址</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-2-2-在线文档" class="sidebar-link">2.5.2.2 在线文档</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-2-3-技术选型" class="sidebar-link">2.5.2.3 技术选型</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-2-4-代码结构" class="sidebar-link">2.5.2.4 代码结构</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_2-5-3-微服务版本" class="sidebar-link">2.5.3 微服务版本</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-3-1-源码地址" class="sidebar-link">2.5.3.1 源码地址</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-3-2-在线文档" class="sidebar-link">2.5.3.2 在线文档</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-3-3-技术选型" class="sidebar-link">2.5.3.3 技术选型</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-3-4-代码结构" class="sidebar-link">2.5.3.4 代码结构</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_2-5-4-移动版" class="sidebar-link">2.5.4 移动版</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-4-1-源码地址" class="sidebar-link">2.5.4.1 源码地址</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-4-2-在线文档" class="sidebar-link">2.5.4.2 在线文档</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-4-3-技术选型" class="sidebar-link">2.5.4.3 技术选型</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_2-5-4-4-代码结构" class="sidebar-link">2.5.4.4 代码结构</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#三、源码下载" class="sidebar-link">三、源码下载</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_3-1-说明" class="sidebar-link">3.1 说明</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_3-2-下载" class="sidebar-link">3.2 下载</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_3-3-idea克隆" class="sidebar-link">3.3 Idea克隆</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#四、项目上手技巧" class="sidebar-link">四、项目上手技巧</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_4-1-标准开源项目" class="sidebar-link">4.1 标准开源项目</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-1-1-看readme-md" class="sidebar-link">4.1.1 看README.md</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-1-2-看演示项目" class="sidebar-link">4.1.2 看演示项目</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-1-3-看文档" class="sidebar-link">4.1.3 看文档</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_4-2-非标准开源项目" class="sidebar-link">4.2 非标准开源项目</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-2-1-看readme-md" class="sidebar-link">4.2.1 看README.md</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-2-2-看jar依赖" class="sidebar-link">4.2.2 看Jar依赖</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-2-3-看代码结构" class="sidebar-link">4.2.3 看代码结构</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-2-4-yy联想" class="sidebar-link">4.2.4 YY联想</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_4-3-若依初探" class="sidebar-link">4.3 若依初探</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-3-1-标准开源项目" class="sidebar-link">4.3.1 标准开源项目</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_4-3-1-1-看readme-md" class="sidebar-link">4.3.1.1 看README.md</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_4-3-1-2-看演示项目" class="sidebar-link">4.3.1.2 看演示项目</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_4-3-1-3-看文档" class="sidebar-link">4.3.1.3 看文档</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-3-2-架构设计图" class="sidebar-link">4.3.2 架构设计图</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_4-3-3-代码结构" class="sidebar-link">4.3.3 代码结构</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#五、环境准备" class="sidebar-link">五、环境准备</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_5-1-语言环境" class="sidebar-link">5.1 语言环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-1-1-java环境" class="sidebar-link">5.1.1 Java环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-1-2-node-js环境" class="sidebar-link">5.1.2 node.js环境</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_5-2-数据库环境" class="sidebar-link">5.2 数据库环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-2-1-mysql环境" class="sidebar-link">5.2.1 MySQL环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-2-2-redis环境" class="sidebar-link">5.2.2 Redis环境</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_5-3-组件环境" class="sidebar-link">5.3 组件环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-3-1-nacos环境" class="sidebar-link">5.3.1 Nacos环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-3-2-sentinel环境" class="sidebar-link">5.3.2 Sentinel环境</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_5-3-3-seata环境" class="sidebar-link">5.3.3 Seata环境</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#六、项目配置与启动" class="sidebar-link">六、项目配置与启动</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_6-1-后端配置" class="sidebar-link">6.1 后端配置</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_6-1-1-数据库" class="sidebar-link">6.1.1 数据库</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_6-1-2-nacos配置" class="sidebar-link">6.1.2 Nacos配置</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_6-1-3-项目配置文件" class="sidebar-link">6.1.3 项目配置文件</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_6-2-后端启动" class="sidebar-link">6.2 后端启动</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_6-3-前端配置与启动" class="sidebar-link">6.3 前端配置与启动</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_6-4-访问" class="sidebar-link">6.4 访问</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#七、模块解读" class="sidebar-link">七、模块解读</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_7-1-解读技巧" class="sidebar-link">7.1 解读技巧</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_7-2-请求闭环" class="sidebar-link">7.2 请求闭环</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-2-1-前端" class="sidebar-link">7.2.1 前端</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-2-2-后端" class="sidebar-link">7.2.2 后端</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_7-3-网关模块" class="sidebar-link">7.3 网关模块</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_7-4-鉴权模块" class="sidebar-link">7.4 鉴权模块</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-4-1-外部鉴权" class="sidebar-link">7.4.1 外部鉴权</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-1-1-步骤1-jwt获取" class="sidebar-link">7.4.1.1 步骤1：JWT获取</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-1-2-步骤2-jwt鉴权" class="sidebar-link">7.4.1.2 步骤2：JWT鉴权</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-1-3-步骤3-jwt鉴权实现" class="sidebar-link">7.4.1.3 步骤3：JWT鉴权实现</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-4-2-内部鉴权" class="sidebar-link">7.4.2 内部鉴权</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-2-1-步骤1-远程调用过程" class="sidebar-link">7.4.2.1 步骤1：远程调用过程</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-2-2-步骤2-远程正式调用" class="sidebar-link">7.4.2.2 步骤2：远程正式调用</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-4-2-3-步骤3-内部鉴权" class="sidebar-link">7.4.2.3 步骤3：内部鉴权</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_7-5-代码生成模块" class="sidebar-link">7.5 代码生成模块</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-5-1-步骤1-创建表" class="sidebar-link">7.5.1 步骤1：创建表</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-5-2-步骤2-导入新建表" class="sidebar-link">7.5.2 步骤2：导入新建表</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-5-3-步骤3-定制代码信息" class="sidebar-link">7.5.3 步骤3：定制代码信息</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-3-1-基本信息" class="sidebar-link">7.5.3.1 基本信息</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-3-2-字段信息" class="sidebar-link">7.5.3.2 字段信息</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-3-3-生成信息" class="sidebar-link">7.5.3.3 生成信息</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-3-4-预览" class="sidebar-link">7.5.3.4 预览</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-3-5-生成代码" class="sidebar-link">7.5.3.5 生成代码</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_7-5-4-步骤4-使用代码" class="sidebar-link">7.5.4 步骤4：使用代码</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-4-1-employeemenu-sql" class="sidebar-link">7.5.4.1 employeeMenu.sql</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-4-2-vue" class="sidebar-link">7.5.4.2 vue</a></li><li class="sidebar-sub-header level5"><a href="/pages/eed55d/#_7-5-4-3-main" class="sidebar-link">7.5.4.3 main</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#八、定制微服务" class="sidebar-link">八、定制微服务</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_8-1-需求" class="sidebar-link">8.1 需求</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_8-2-代码结构" class="sidebar-link">8.2 代码结构</a></li><li class="sidebar-sub-header level3"><a href="/pages/eed55d/#_8-3-实现步骤" class="sidebar-link">8.3 实现步骤</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_8-3-1-步骤1-定义ruoyi-api-test" class="sidebar-link">8.3.1 步骤1：定义ruoyi-api-test</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_8-3-2-步骤2-等级ruoyi-api-test依赖" class="sidebar-link">8.3.2 步骤2：等级ruoyi-api-test依赖</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_8-3-3-步骤3-定义ruoyi-modules-test" class="sidebar-link">8.3.3 步骤3：定义ruoyi-modules-test</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_8-3-4-步骤4-定制微服务配置文件" class="sidebar-link">8.3.4 步骤4：定制微服务配置文件</a></li><li class="sidebar-sub-header level4"><a href="/pages/eed55d/#_8-3-5-步骤5-定制网关微服务路由" class="sidebar-link">8.3.5 步骤5：定制网关微服务路由</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/eed55d/#九、小结与作业" class="sidebar-link">九、小结与作业</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>技术增值</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-06225672><div class="articleInfo" data-v-06225672><ul class="breadcrumbs" data-v-06225672><li data-v-06225672><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-06225672></a></li> <li data-v-06225672><a href="/categories/?category=Java%E9%80%9F%E9%80%9A" title="分类" data-v-06225672>Java速通</a></li><li data-v-06225672><a href="/categories/?category=%E8%84%9A%E6%89%8B%E6%9E%B6" title="分类" data-v-06225672>脚手架</a></li></ul> <div class="info" data-v-06225672><div title="作者" class="author iconfont icon-touxiang" data-v-06225672><a href="https://github.com/langfeiyes" target="_blank" title="作者" class="beLink" data-v-06225672>langfeiyes</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-06225672><a href="javascript:;" data-v-06225672>2024-03-12</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src="">脚手架-RuoYi-Cloud 微服务版<!----></h1>  <div class="theme-vdoing-content content__default"><h1 id="脚手架-ruoyi-cloud-微服务版"><a href="#脚手架-ruoyi-cloud-微服务版" class="header-anchor">#</a> 脚手架-RuoYi-Cloud 微服务版</h1> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626191330354.png" alt=""></p> <h2 id="一、今日学习内容与目标"><a href="#一、今日学习内容与目标" class="header-anchor">#</a> 一、今日学习内容与目标</h2> <h3 id="_1-1-前置知识点"><a href="#_1-1-前置知识点" class="header-anchor">#</a> 1.1 前置知识点</h3> <ul><li>Java WEB 知识体系</li> <li>Spring、SpringMVC、SpringBoot  传统MVC框架体系</li> <li>MyBatis 持久层框架体系</li> <li>SpringCloud Alibaba 微服务落地方案</li> <li>Maven、Git、Idea 常规开发工具</li> <li>MySQL、Redis 常见关系/非关系型数据库</li></ul> <h3 id="_1-2-教学目标"><a href="#_1-2-教学目标" class="header-anchor">#</a> 1.2 教学目标</h3> <ul><li>掌握陌生项目解读技巧</li> <li>掌握若依(RuoYi-Cloud)框架</li> <li>掌握SpringCloud Alibaba体系项目开发套路</li></ul> <h2 id="二、框架介绍"><a href="#二、框架介绍" class="header-anchor">#</a> 二、框架介绍</h2> <h3 id="_2-1-简介"><a href="#_2-1-简介" class="header-anchor">#</a> 2.1 简介</h3> <p>一直想做一款后台管理系统，看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序，如网站管理后台，网站会员中心，CMS，CRM，OA。所有前端后台代码封装过后十分精简易上手，出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。</p> <p>性别男，若依是给女儿取的名字（寓意：你若不离不弃，我必生死相依）</p> <p>若依是一套全部开源的快速开发平台，毫无保留给个人及企业免费使用。</p> <h3 id="_2-2-内置功能"><a href="#_2-2-内置功能" class="header-anchor">#</a> 2.2 内置功能</h3> <ul><li>用户管理：用户是系统操作者，该功能主要完成系统用户配置。</li> <li>部门管理：配置系统组织机构（公司、部门、小组），树结构展现支持数据权限。</li> <li>岗位管理：配置系统用户所属担任职务。</li> <li>菜单管理：配置系统菜单，操作权限，按钮权限标识等。</li> <li>角色管理：角色菜单权限分配、设置角色按机构进行数据范围权限划分。</li> <li>字典管理：对系统中经常使用的一些较为固定的数据进行维护。</li> <li>参数管理：对系统动态配置常用参数。</li> <li>通知公告：系统通知公告信息发布维护。</li> <li>操作日志：系统正常操作日志记录和查询；系统异常信息日志记录和查询。</li> <li>登录日志：系统登录日志记录查询包含登录异常。</li> <li>在线用户：当前系统中活跃用户状态监控。</li> <li>定时任务：在线（添加、修改、删除)任务调度包含执行结果日志。</li> <li>代码生成：前后端代码的生成（java、html、xml、sql）支持CRUD下载 。</li> <li>系统接口：根据业务代码自动生成相关的api接口文档。</li> <li>服务监控：监视当前系统CPU、内存、磁盘、堆栈等相关信息。</li> <li>缓存监控：对系统的缓存查询，删除、清空等操作。</li> <li>在线构建器：拖动表单元素生成相应的HTML代码。</li> <li>连接池监视：监视当前系统数据库连接池状态，可进行分析SQL找出系统性能瓶颈。</li></ul> <h3 id="_2-3-主要特性"><a href="#_2-3-主要特性" class="header-anchor">#</a> 2.3 主要特性</h3> <ul><li>完全响应式布局（支持电脑、平板、手机等所有主流设备）</li> <li>强大的一键生成功能（包括控制器、模型、视图、菜单等）</li> <li>支持多数据源，简单配置即可实现切换。</li> <li>支持按钮及数据权限，可自定义部门数据权限。</li> <li>对常用js插件进行二次封装，使js代码变得简洁，更加易维护</li> <li>完善的XSS防范及脚本过滤，彻底杜绝XSS攻击</li> <li>Maven多项目依赖，模块及插件分项目，尽量松耦合，方便模块升级、增减模块。</li> <li>国际化支持，服务端及客户端支持</li> <li>完善的日志记录体系简单注解即可实现</li> <li>支持服务监控，数据监控，缓存监控功能。</li></ul> <h3 id="_2-4-演示地址"><a href="#_2-4-演示地址" class="header-anchor">#</a> 2.4 演示地址</h3> <p>http://demo.ruoyi.vip/login</p> <p>账号：admin 密码：admin123</p> <h3 id="_2-5-分类"><a href="#_2-5-分类" class="header-anchor">#</a> 2.5 分类</h3> <h4 id="_2-5-1-传统版"><a href="#_2-5-1-传统版" class="header-anchor">#</a> 2.5.1 <strong>传统版</strong></h4> <h5 id="_2-5-1-1-源码地址"><a href="#_2-5-1-1-源码地址" class="header-anchor">#</a> 2.5.1.1 源码地址</h5> <p>https://gitee.com/y_project/RuoYi</p> <h5 id="_2-5-1-2-在线文档"><a href="#_2-5-1-2-在线文档" class="header-anchor">#</a> 2.5.1.2 在线文档</h5> <p>http://doc.ruoyi.vip/ruoyi/</p> <h5 id="_2-5-1-3-技术选型"><a href="#_2-5-1-3-技术选型" class="header-anchor">#</a> 2.5.1.3 技术选型</h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626185815229.png" alt=""></p> <h5 id="_2-5-1-4-代码结构"><a href="#_2-5-1-4-代码结构" class="header-anchor">#</a> 2.5.1.4 代码结构</h5> <div class="language-java line-numbers-mode"><pre class="language-java"><code>com<span class="token punctuation">.</span>ruoyi     
├── common            <span class="token comment">// 工具类</span>
│       └── annotation                    <span class="token comment">// 自定义注解</span>
│       └── config                        <span class="token comment">// 全局配置</span>
│       └── constant                      <span class="token comment">// 通用常量</span>
│       └── core                          <span class="token comment">// 核心控制</span>
│       └── enums                         <span class="token comment">// 通用枚举</span>
│       └── exception                     <span class="token comment">// 通用异常</span>
│       └── json                          <span class="token comment">// JSON数据处理</span>
│       └── utils                         <span class="token comment">// 通用类处理</span>
│       └── xss                           <span class="token comment">// XSS过滤处理</span>
├── framework         <span class="token comment">// 框架核心</span>
│       └── aspectj                       <span class="token comment">// 注解实现</span>
│       └── config                        <span class="token comment">// 系统配置</span>
│       └── datasource                    <span class="token comment">// 数据权限</span>
│       └── interceptor                   <span class="token comment">// 拦截器</span>
│       └── manager                       <span class="token comment">// 异步处理</span>
│       └── shiro                         <span class="token comment">// 权限控制</span>
│       └── web                           <span class="token comment">// 前端控制</span>
├── ruoyi<span class="token operator">-</span>generator   <span class="token comment">// 代码生成（不用可移除）</span>
├── ruoyi<span class="token operator">-</span>quartz      <span class="token comment">// 定时任务（不用可移除）</span>
├── ruoyi<span class="token operator">-</span>system      <span class="token comment">// 系统代码</span>
├── ruoyi<span class="token operator">-</span>admin       <span class="token comment">// 后台服务</span>
├── ruoyi<span class="token operator">-</span>xxxxxx      <span class="token comment">// 其他模块</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><h4 id="_2-5-2-前后端分离版本"><a href="#_2-5-2-前后端分离版本" class="header-anchor">#</a> 2.5.2 前后端分离版本</h4> <h5 id="_2-5-2-1-源码地址"><a href="#_2-5-2-1-源码地址" class="header-anchor">#</a> 2.5.2.1 源码地址</h5> <p>https://gitee.com/y_project/RuoYi-Vue</p> <h5 id="_2-5-2-2-在线文档"><a href="#_2-5-2-2-在线文档" class="header-anchor">#</a> 2.5.2.2 在线文档</h5> <p>http://doc.ruoyi.vip/ruoyi-vue/</p> <h5 id="_2-5-2-3-技术选型"><a href="#_2-5-2-3-技术选型" class="header-anchor">#</a> 2.5.2.3 技术选型</h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626190400192.png" alt=""></p> <h5 id="_2-5-2-4-代码结构"><a href="#_2-5-2-4-代码结构" class="header-anchor">#</a> 2.5.2.4 代码结构</h5> <p><strong>后端结构</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>com<span class="token punctuation">.</span>ruoyi     
├── common            <span class="token comment">// 工具类</span>
│       └── annotation                    <span class="token comment">// 自定义注解</span>
│       └── config                        <span class="token comment">// 全局配置</span>
│       └── constant                      <span class="token comment">// 通用常量</span>
│       └── core                          <span class="token comment">// 核心控制</span>
│       └── enums                         <span class="token comment">// 通用枚举</span>
│       └── exception                     <span class="token comment">// 通用异常</span>
│       └── filter                        <span class="token comment">// 过滤器处理</span>
│       └── utils                         <span class="token comment">// 通用类处理</span>
├── framework         <span class="token comment">// 框架核心</span>
│       └── aspectj                       <span class="token comment">// 注解实现</span>
│       └── config                        <span class="token comment">// 系统配置</span>
│       └── datasource                    <span class="token comment">// 数据权限</span>
│       └── interceptor                   <span class="token comment">// 拦截器</span>
│       └── manager                       <span class="token comment">// 异步处理</span>
│       └── security                      <span class="token comment">// 权限控制</span>
│       └── web                           <span class="token comment">// 前端控制</span>
├── ruoyi<span class="token operator">-</span>generator   <span class="token comment">// 代码生成（可移除）</span>
├── ruoyi<span class="token operator">-</span>quartz      <span class="token comment">// 定时任务（可移除）</span>
├── ruoyi<span class="token operator">-</span>system      <span class="token comment">// 系统代码</span>
├── ruoyi<span class="token operator">-</span>admin       <span class="token comment">// 后台服务</span>
├── ruoyi<span class="token operator">-</span>xxxxxx      <span class="token comment">// 其他模块</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><p><strong>前端结构</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>├── build                      <span class="token comment">// 构建相关  </span>
├── bin                        <span class="token comment">// 执行脚本</span>
├── <span class="token keyword">public</span>                     <span class="token comment">// 公共文件</span>
│   ├── favicon<span class="token punctuation">.</span>ico            <span class="token comment">// favicon图标</span>
│   └── index<span class="token punctuation">.</span>html             <span class="token comment">// html模板</span>
│   └── robots<span class="token punctuation">.</span>txt             <span class="token comment">// 反爬虫</span>
├── src                        <span class="token comment">// 源代码</span>
│   ├── api                    <span class="token comment">// 所有请求</span>
│   ├── assets                 <span class="token comment">// 主题 字体等静态资源</span>
│   ├── components             <span class="token comment">// 全局公用组件</span>
│   ├── directive              <span class="token comment">// 全局指令</span>
│   ├── layout                 <span class="token comment">// 布局</span>
│   ├── plugins                <span class="token comment">// 通用方法</span>
│   ├── router                 <span class="token comment">// 路由</span>
│   ├── store                  <span class="token comment">// 全局 store管理</span>
│   ├── utils                  <span class="token comment">// 全局公用方法</span>
│   ├── views                  <span class="token comment">// view</span>
│   ├── <span class="token class-name">App</span><span class="token punctuation">.</span>vue                <span class="token comment">// 入口页面</span>
│   ├── main<span class="token punctuation">.</span>js                <span class="token comment">// 入口 加载组件 初始化等</span>
│   ├── permission<span class="token punctuation">.</span>js          <span class="token comment">// 权限管理</span>
│   └── settings<span class="token punctuation">.</span>js            <span class="token comment">// 系统配置</span>
├── <span class="token punctuation">.</span>editorconfig              <span class="token comment">// 编码格式</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>development           <span class="token comment">// 开发环境配置</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>production            <span class="token comment">// 生产环境配置</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>staging               <span class="token comment">// 测试环境配置</span>
├── <span class="token punctuation">.</span>eslintignore              <span class="token comment">// 忽略语法检查</span>
├── <span class="token punctuation">.</span>eslintrc<span class="token punctuation">.</span>js               <span class="token comment">// eslint 配置项</span>
├── <span class="token punctuation">.</span>gitignore                 <span class="token comment">// git 忽略项</span>
├── babel<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js            <span class="token comment">// babel.config.js</span>
├── <span class="token keyword">package</span><span class="token punctuation">.</span>json               <span class="token comment">// package.json</span>
└── vue<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js              <span class="token comment">// vue.config.js</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><h4 id="_2-5-3-微服务版本"><a href="#_2-5-3-微服务版本" class="header-anchor">#</a> 2.5.3 微服务版本</h4> <h5 id="_2-5-3-1-源码地址"><a href="#_2-5-3-1-源码地址" class="header-anchor">#</a> 2.5.3.1 源码地址</h5> <p>https://gitee.com/y_project/RuoYi-Cloud</p> <h5 id="_2-5-3-2-在线文档"><a href="#_2-5-3-2-在线文档" class="header-anchor">#</a> 2.5.3.2 在线文档</h5> <p>http://doc.ruoyi.vip/ruoyi-cloud/</p> <h5 id="_2-5-3-3-技术选型"><a href="#_2-5-3-3-技术选型" class="header-anchor">#</a> 2.5.3.3 技术选型</h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626190728296.png" alt=""></p> <h5 id="_2-5-3-4-代码结构"><a href="#_2-5-3-4-代码结构" class="header-anchor">#</a> 2.5.3.4 代码结构</h5> <p><strong>后端结构</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>com<span class="token punctuation">.</span>ruoyi     
├── ruoyi<span class="token operator">-</span>ui              <span class="token comment">// 前端框架 [80]</span>
├── ruoyi<span class="token operator">-</span>gateway         <span class="token comment">// 网关模块 [8080]</span>
├── ruoyi<span class="token operator">-</span>auth            <span class="token comment">// 认证中心 [9200]</span>
├── ruoyi<span class="token operator">-</span>api             <span class="token comment">// 接口模块</span>
│       └── ruoyi<span class="token operator">-</span>api<span class="token operator">-</span>system                          <span class="token comment">// 系统接口</span>
├── ruoyi<span class="token operator">-</span>common          <span class="token comment">// 通用模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>core                         <span class="token comment">// 核心模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>datascope                    <span class="token comment">// 权限范围</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>datasource                   <span class="token comment">// 多数据源</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>log                          <span class="token comment">// 日志记录</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>redis                        <span class="token comment">// 缓存服务</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>seata                        <span class="token comment">// 分布式事务</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>security                     <span class="token comment">// 安全模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>swagger                      <span class="token comment">// 系统接口</span>
├── ruoyi<span class="token operator">-</span>modules         <span class="token comment">// 业务模块</span>
│       └── ruoyi<span class="token operator">-</span>system                              <span class="token comment">// 系统模块 [9201]</span>
│       └── ruoyi<span class="token operator">-</span>gen                                 <span class="token comment">// 代码生成 [9202]</span>
│       └── ruoyi<span class="token operator">-</span>job                                 <span class="token comment">// 定时任务 [9203]</span>
│       └── ruoyi<span class="token operator">-</span>file                                <span class="token comment">// 文件服务 [9300]</span>
├── ruoyi<span class="token operator">-</span>visual          <span class="token comment">// 图形化管理模块</span>
│       └── ruoyi<span class="token operator">-</span>visual<span class="token operator">-</span>monitor                      <span class="token comment">// 监控中心 [9100]</span>
├──pom<span class="token punctuation">.</span>xml                <span class="token comment">// 公共依赖</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><p><strong>前端结构</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>├── build                      <span class="token comment">// 构建相关  </span>
├── bin                        <span class="token comment">// 执行脚本</span>
├── <span class="token keyword">public</span>                     <span class="token comment">// 公共文件</span>
│   ├── favicon<span class="token punctuation">.</span>ico            <span class="token comment">// favicon图标</span>
│   └── index<span class="token punctuation">.</span>html             <span class="token comment">// html模板</span>
├── src                        <span class="token comment">// 源代码</span>
│   ├── api                    <span class="token comment">// 所有请求</span>
│   ├── assets                 <span class="token comment">// 主题 字体等静态资源</span>
│   ├── components             <span class="token comment">// 全局公用组件</span>
│   ├── directive              <span class="token comment">// 全局指令</span>
│   ├── layout                 <span class="token comment">// 布局</span>
│   ├── plugins                <span class="token comment">// 通用方法</span>
│   ├── router                 <span class="token comment">// 路由</span>
│   ├── store                  <span class="token comment">// 全局 store管理</span>
│   ├── utils                  <span class="token comment">// 全局公用方法</span>
│   ├── views                  <span class="token comment">// view</span>
│   ├── <span class="token class-name">App</span><span class="token punctuation">.</span>vue                <span class="token comment">// 入口页面</span>
│   ├── main<span class="token punctuation">.</span>js                <span class="token comment">// 入口 加载组件 初始化等</span>
│   ├── permission<span class="token punctuation">.</span>js          <span class="token comment">// 权限管理</span>
│   └── settings<span class="token punctuation">.</span>js            <span class="token comment">// 系统配置</span>
├── <span class="token punctuation">.</span>editorconfig              <span class="token comment">// 编码格式</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>development           <span class="token comment">// 开发环境配置</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>production            <span class="token comment">// 生产环境配置</span>
├── <span class="token punctuation">.</span>env<span class="token punctuation">.</span>staging               <span class="token comment">// 测试环境配置</span>
├── <span class="token punctuation">.</span>eslintignore              <span class="token comment">// 忽略语法检查</span>
├── <span class="token punctuation">.</span>eslintrc<span class="token punctuation">.</span>js               <span class="token comment">// eslint 配置项</span>
├── <span class="token punctuation">.</span>gitignore                 <span class="token comment">// git 忽略项</span>
├── babel<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js            <span class="token comment">// babel.config.js</span>
├── <span class="token keyword">package</span><span class="token punctuation">.</span>json               <span class="token comment">// package.json</span>
└── vue<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js              <span class="token comment">// vue.config.js</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><h4 id="_2-5-4-移动版"><a href="#_2-5-4-移动版" class="header-anchor">#</a> 2.5.4 移动版</h4> <h5 id="_2-5-4-1-源码地址"><a href="#_2-5-4-1-源码地址" class="header-anchor">#</a> 2.5.4.1 源码地址</h5> <p>https://gitee.com/y_project/RuoYi-App</p> <h5 id="_2-5-4-2-在线文档"><a href="#_2-5-4-2-在线文档" class="header-anchor">#</a> 2.5.4.2 在线文档</h5> <p>http://doc.ruoyi.vip/ruoyi-app/</p> <h5 id="_2-5-4-3-技术选型"><a href="#_2-5-4-3-技术选型" class="header-anchor">#</a> 2.5.4.3 技术选型</h5> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626191035895.png" alt=""></em></p> <h5 id="_2-5-4-4-代码结构"><a href="#_2-5-4-4-代码结构" class="header-anchor">#</a> 2.5.4.4 代码结构</h5> <div class="language-java line-numbers-mode"><pre class="language-java"><code>├── api                        <span class="token comment">// 所有请求  </span>
├── components                 <span class="token comment">// 全局公用组件</span>
├── pages                      <span class="token comment">// 页面文件</span>
├── plugins                    <span class="token comment">// 通用方法</span>
├── store                      <span class="token comment">// 全局 store管理</span>
├── utils                      <span class="token comment">// 公用方法</span>
├── <span class="token keyword">static</span>                     <span class="token comment">// 公共文件</span>
│   ├── favicon<span class="token punctuation">.</span>ico            <span class="token comment">// favicon图标</span>
│   └── index<span class="token punctuation">.</span>html             <span class="token comment">// html模板</span>
│   └── logo<span class="token punctuation">.</span>png               <span class="token comment">// logo图片</span>
├── uni_modules                <span class="token comment">// uniui组件</span>
│   ├── uni<span class="token operator">-</span>badge              <span class="token comment">// 数字角标</span>
│   ├── <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>              <span class="token comment">// ........</span>
│   ├── <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>              <span class="token comment">// ........</span>
├── <span class="token class-name">App</span><span class="token punctuation">.</span>vue                    <span class="token comment">// 应用配置</span>
├── config<span class="token punctuation">.</span>js                  <span class="token comment">// 环境配置</span>
├── main<span class="token punctuation">.</span>js                    <span class="token comment">// Vue初始化入口文件</span>
├── manifest<span class="token punctuation">.</span>json              <span class="token comment">// 配置打包</span>
├── pages<span class="token punctuation">.</span>json                 <span class="token comment">// 配置页面路由</span>
├── permission<span class="token punctuation">.</span>js              <span class="token comment">// 权限拦截</span>
├── uni<span class="token punctuation">.</span>scss                   <span class="token comment">// 全局样式变量</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><h2 id="三、源码下载"><a href="#三、源码下载" class="header-anchor">#</a> 三、源码下载</h2> <h3 id="_3-1-说明"><a href="#_3-1-说明" class="header-anchor">#</a> 3.1 说明</h3> <p>本教程以若依微服版(RuoYi-Cloud)为解读蓝本，所有源码、文件、截图、演示均为该版本。</p> <h3 id="_3-2-下载"><a href="#_3-2-下载" class="header-anchor">#</a> 3.2 下载</h3> <p>国内：https://gitee.com/y_project/RuoYi-Cloud</p> <p>国外：https://github.com/yangzongzhuan/RuoYi-Cloud</p> <h3 id="_3-3-idea克隆"><a href="#_3-3-idea克隆" class="header-anchor">#</a> 3.3 Idea克隆</h3> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626193023708.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626193052882.png" alt=""></p> <p><img src="images/image-20230626193121648.png" alt="image-20230626193121648"></p> <h2 id="四、项目上手技巧"><a href="#四、项目上手技巧" class="header-anchor">#</a> 四、项目上手技巧</h2> <h3 id="_4-1-标准开源项目"><a href="#_4-1-标准开源项目" class="header-anchor">#</a> 4.1 标准开源项目</h3> <p>标准开源项目：指符合特定标准和规范的开源软件项目。这些标准和规范通常由开源社区、行业组织或相关标准制定机构定义和推广。标准开源项目的目的是提供一致的质量标准和最佳实践，以促进开源软件的可靠性、互操作性和可持续发展。</p> <p><strong>大白话：代码、文件、教程等各种配套都齐全的项目。</strong></p> <h4 id="_4-1-1-看readme-md"><a href="#_4-1-1-看readme-md" class="header-anchor">#</a> 4.1.1 看README.md</h4> <p>标准开源项目，都是有一个README.md这种文档，这个文档是项目的简介，一般会用大白话方式讲清楚项目背景，项目技术点，项目具体使用等。</p> <h4 id="_4-1-2-看演示项目"><a href="#_4-1-2-看演示项目" class="header-anchor">#</a> 4.1.2 看演示项目</h4> <blockquote><p>http://vue.ruoyi.vip/login?redirect=%2Findex</p></blockquote> <p>好处：快速了解项目具体功能，能做啥，实现效果怎么样。</p> <h4 id="_4-1-3-看文档"><a href="#_4-1-3-看文档" class="header-anchor">#</a> 4.1.3 看文档</h4> <blockquote><p>http://doc.ruoyi.vip/ruoyi-cloud/</p></blockquote> <p>好处：该有的都有了</p> <p><strong>一个问题：看文档，看哪些内容？</strong></p> <p>0&gt;视频教程(如果有)</p> <p>1&gt;项目结构/架构(如果有)</p> <p>2&gt;技术选型</p> <p>3&gt;功能模块</p> <p>4&gt;项目部署</p> <p>5&gt;项目其他</p> <h3 id="_4-2-非标准开源项目"><a href="#_4-2-非标准开源项目" class="header-anchor">#</a> 4.2 非标准开源项目</h3> <p>非标准开源项目是指没有遵循特定标准或规范的开源软件项目。这些项目可能是由个人、小团队或组织开发，其开发方式和治理模式可能与传统的标准开源项目有所不同。</p> <p><strong>大白话：代码、文件、教程等各种配套都不齐全的项目。</strong></p> <h4 id="_4-2-1-看readme-md"><a href="#_4-2-1-看readme-md" class="header-anchor">#</a> 4.2.1 看README.md</h4> <p>如果有，必须看。但一般情况，都是下面这种：啥都是没有</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626195720645.png" alt=""></p> <h4 id="_4-2-2-看jar依赖"><a href="#_4-2-2-看jar依赖" class="header-anchor">#</a> 4.2.2 看Jar依赖</h4> <p>没有使用Maven/Gradle传统项目，比如Java SE/JavaWeb项目，Jar依赖一般放置在lib文件夹，优先找它</p> <p>如果使用Maven/Gradle常规项目，找pom.xml文件或build.gradle</p> <p><strong>一个问题：看Jar依赖目的是啥？</strong></p> <p>1&gt;大体把握项目技术栈</p> <p>​    要求：结合技术栈，YY一下代码可能的结构，后续项目解读时有参照蓝本。</p> <p>​    比如：
​         MyBatis---domain----mapper.java-----mapper.xml</p> <p>​         Springboot----Spring----Springmvc----Controller----启动类</p> <p>​		 SpringCloud Alibaba-----8个基本组件</p> <p>2&gt;大体推测项目有哪些功能</p> <p>​    要求：常见的功能jar有熟悉，不认识，可以搜。</p> <p>​     比如：</p> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>io.springfox<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>springfox-swagger-ui<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>${swagger.fox.version}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>io.jsonwebtoken<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>jjwt<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.poi<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>poi-ooxml<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h4 id="_4-2-3-看代码结构"><a href="#_4-2-3-看代码结构" class="header-anchor">#</a> 4.2.3 看代码结构</h4> <p>没有文档的帮助，只能借助代码结构名称大体推测项目可能具有模块，拥有的功能。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626205452813.png" alt=""></p> <h4 id="_4-2-4-yy联想"><a href="#_4-2-4-yy联想" class="header-anchor">#</a> 4.2.4 YY联想</h4> <p>非开源项目最麻烦一个点就是文件不齐全，少文档，少sql数据库，甚至代码不完整。这时候想解读通这代码就需要很丰富的想象能力。</p> <blockquote><p>类似一拳超人中地表最强的男人：King ！哥的厉害全靠你想象</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/e850352ac65c10381531e3b5b1119313b07e897d.jpg" alt=""></p> <p>这个得结合个人开发经验，项目经验，生活阅历，连蒙靠猜推测去补齐项目逻辑啦。</p> <p>比如：</p> <p>缺SQL：找Mapper.xml/domain实体补齐</p> <p>缺Jar包：根据项目启动报错信息，缺哪个补哪个</p> <p>缺配置文件：项目依赖用到哪些jar，结合常规配置，补齐配置</p> <p>缺少各种环境：结合个人开发经验，尝试补齐。</p> <h3 id="_4-3-若依初探"><a href="#_4-3-若依初探" class="header-anchor">#</a> 4.3 若依初探</h3> <p>若依脚手架算是一个较为标准的开源项目了，那它阶段就按照标准项目方式解读即可。</p> <h4 id="_4-3-1-标准开源项目"><a href="#_4-3-1-标准开源项目" class="header-anchor">#</a> 4.3.1 标准开源项目</h4> <h5 id="_4-3-1-1-看readme-md"><a href="#_4-3-1-1-看readme-md" class="header-anchor">#</a> 4.3.1.1 看README.md</h5> <p>--了解项目整体</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626210024682.png" alt=""></p> <h5 id="_4-3-1-2-看演示项目"><a href="#_4-3-1-2-看演示项目" class="header-anchor">#</a> 4.3.1.2 看演示项目</h5> <p>--了解项目效果</p> <p>地址：http://vue.ruoyi.vip/index</p> <p>账号密码：admin/admin123</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626210112384.png" alt=""></p> <h5 id="_4-3-1-3-看文档"><a href="#_4-3-1-3-看文档" class="header-anchor">#</a> 4.3.1.3 看文档</h5> <p>--了解项目细节</p> <p>地址：http://doc.ruoyi.vip/ruoyi-cloud/</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626210146701.png" alt=""></p> <h4 id="_4-3-2-架构设计图"><a href="#_4-3-2-架构设计图" class="header-anchor">#</a> 4.3.2 架构设计图</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/up-82e9722ecb846786405a904bafcf19f73f3.png" alt=""></p> <p>从图中解析出RuoYi-Cloud 使用微服务技术栈</p> <p>网关：Gateway</p> <p>远程调用：Ribbon/Feign</p> <p>注册中心：Nacos Discovery</p> <p>熔断降级：Sentinel</p> <p>配置中心：Nacos Config</p> <p>链路追踪：Sleuth+ZipKin/SkyWalking   （没有集成，需要自己加）</p> <h4 id="_4-3-3-代码结构"><a href="#_4-3-3-代码结构" class="header-anchor">#</a> 4.3.3 代码结构</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code>com<span class="token punctuation">.</span>ruoyi     
├── ruoyi<span class="token operator">-</span>ui              <span class="token comment">// 前端框架 [80]</span>
├── ruoyi<span class="token operator">-</span>gateway         <span class="token comment">// 网关模块 [8080]</span>
├── ruoyi<span class="token operator">-</span>auth            <span class="token comment">// 认证中心 [9200]</span>
├── ruoyi<span class="token operator">-</span>api             <span class="token comment">// 接口模块</span>
│       └── ruoyi<span class="token operator">-</span>api<span class="token operator">-</span>system                          <span class="token comment">// 系统接口</span>
├── ruoyi<span class="token operator">-</span>common          <span class="token comment">// 通用模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>core                         <span class="token comment">// 核心模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>datascope                    <span class="token comment">// 权限范围</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>datasource                   <span class="token comment">// 多数据源</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>log                          <span class="token comment">// 日志记录</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>redis                        <span class="token comment">// 缓存服务</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>seata                        <span class="token comment">// 分布式事务</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>security                     <span class="token comment">// 安全模块</span>
│       └── ruoyi<span class="token operator">-</span>common<span class="token operator">-</span>swagger                      <span class="token comment">// 系统接口</span>
├── ruoyi<span class="token operator">-</span>modules         <span class="token comment">// 业务模块</span>
│       └── ruoyi<span class="token operator">-</span>system                              <span class="token comment">// 系统模块 [9201]</span>
│       └── ruoyi<span class="token operator">-</span>gen                                 <span class="token comment">// 代码生成 [9202]</span>
│       └── ruoyi<span class="token operator">-</span>job                                 <span class="token comment">// 定时任务 [9203]</span>
│       └── ruoyi<span class="token operator">-</span>file                                <span class="token comment">// 文件服务 [9300]</span>
├── ruoyi<span class="token operator">-</span>visual          <span class="token comment">// 图形化管理模块</span>
│       └── ruoyi<span class="token operator">-</span>visual<span class="token operator">-</span>monitor                      <span class="token comment">// 监控中心 [9100]</span>
├──pom<span class="token punctuation">.</span>xml                <span class="token comment">// 公共依赖</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><h2 id="五、环境准备"><a href="#五、环境准备" class="header-anchor">#</a> 五、环境准备</h2> <p>项目运行前提需要准备环境，如果项目提供文档，直接看文档操作即可，如果没有文档，就结合开发经验/项目经验来配置。一般来说，项目环境准备都按照下面几个步骤。</p> <h3 id="_5-1-语言环境"><a href="#_5-1-语言环境" class="header-anchor">#</a> 5.1 语言环境</h3> <p>项目运行离不开语言支持，若依(RuoYi-Cloud)后端为Java项目，需要java环境，前端为Vue项目，需要Node.js环境，运行若依前需要将这些环境安装成功。</p> <h4 id="_5-1-1-java环境"><a href="#_5-1-1-java环境" class="header-anchor">#</a> <strong>5.1.1 Java环境</strong></h4> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626232309233.png" alt=""></em></p> <h4 id="_5-1-2-node-js环境"><a href="#_5-1-2-node-js环境" class="header-anchor">#</a> 5.1.2 <strong>node.js环境</strong></h4> <p>一个node.js环境，一个事npm 软件安装工具</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626232356403.png" alt=""></em></p> <h3 id="_5-2-数据库环境"><a href="#_5-2-数据库环境" class="header-anchor">#</a> 5.2 数据库环境</h3> <p>若依(RuoYi-Cloud)目前使用的数据库暂时只有MySQL跟Redis，后续可以根据项目需要添加其他数据库，比如MongoDB，Elasticsearch等。</p> <h4 id="_5-2-1-mysql环境"><a href="#_5-2-1-mysql环境" class="header-anchor">#</a> 5.2.1 <strong>MySQL环境</strong></h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626232942516.png" alt=""></p> <h4 id="_5-2-2-redis环境"><a href="#_5-2-2-redis环境" class="header-anchor">#</a> 5.2.2 <strong>Redis环境</strong></h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626233013340.png" alt=""></p> <h3 id="_5-3-组件环境"><a href="#_5-3-组件环境" class="header-anchor">#</a> 5.3 组件环境</h3> <p>若依(RuoYi-Cloud)使用的是SpringCloud Alibaba体系微服务落地方法，那就得安装2个必须组件：Nacos跟Sentinel。</p> <h4 id="_5-3-1-nacos环境"><a href="#_5-3-1-nacos环境" class="header-anchor">#</a> 5.3.1 <strong>Nacos环境</strong></h4> <p>若依(RuoYi-Cloud)使用Nacos做注册中心与配置中心，所以需要提前准备该环境。</p> <p>下载路径：https://github.com/alibaba/nacos/releases</p> <p>这里注意，若依(RuoYi-Cloud)要求是Nacos 2.x版本，不要下错</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626233557839.png" alt=""></em></p> <p>进入bin目录启动，执行startup.cmd命令，注意需要使用单例模式启动，否则闪退</p> <div class="language-bash line-numbers-mode"><pre class="language-bash"><code>使用cmd 命令，进入命令框，执行下面命令
startup.cmd <span class="token parameter variable">-m</span> standalone
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626233834740.png" alt=""></p> <h4 id="_5-3-2-sentinel环境"><a href="#_5-3-2-sentinel环境" class="header-anchor">#</a> 5.3.2 <strong>Sentinel环境</strong></h4> <p>若依(RuoYi-Cloud)使用Sentinel熔断降级组件，那么项目启动前，需要提前准备好</p> <p>下载地址：https://github.com/alibaba/Sentinel/releases</p> <p>下载完之后是一个jar包：sentinel-dashboard-1.8.0.jar， 使用java 命令执行就行</p> <div class="language-bash line-numbers-mode"><pre class="language-bash"><code><span class="token function">java</span> <span class="token parameter variable">-Dserver.port</span><span class="token operator">=</span><span class="token number">8080</span> <span class="token parameter variable">-Dcsp.sentinel.dashboard.server</span><span class="token operator">=</span>localhost:8080 <span class="token parameter variable">-Dproject.name</span><span class="token operator">=</span>sentinel-dashboard <span class="token parameter variable">-jar</span> sentinel-dashboard-1.8.0.jar
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h4 id="_5-3-3-seata环境"><a href="#_5-3-3-seata环境" class="header-anchor">#</a> 5.3.3 <strong>Seata环境</strong></h4> <p>若依(RuoYi-Cloud)支持Seata实现分布式事务，如果需要，项目启动前就应该提前准备好</p> <p>下载地址：https://github.com/seata/seata/releases</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626234855831.png" alt=""></em></p> <p>进入bin目录启动，执行seata-server.bat命令</p> <div class="language-bash line-numbers-mode"><pre class="language-bash"><code>seata-server.bat --add-opens<span class="token operator">=</span>java.base/java.lang<span class="token operator">=</span>ALL-UNNAMED
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="六、项目配置与启动"><a href="#六、项目配置与启动" class="header-anchor">#</a> 六、项目配置与启动</h2> <p>当上面环境全部准备好之后，接下来就是项目配置。需要将项目相关配置修改成当前相关环境。</p> <h3 id="_6-1-后端配置"><a href="#_6-1-后端配置" class="header-anchor">#</a> 6.1 后端配置</h3> <h4 id="_6-1-1-数据库"><a href="#_6-1-1-数据库" class="header-anchor">#</a> 6.1.1 数据库</h4> <p><strong>新建数据库：ry-cloud</strong>   存储常规数据</p> <p>字符编码：utf8mb4</p> <p>导入SQL：sql/ry_20230223.sql       sql/quartz.sql(可选--需要定时任务操作必须导入)</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626235621833.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626235633293.png" alt=""></p> <p>**新建数据库：ry-config **   存储nacos配置数据</p> <p>字符编码：utf8mb4</p> <p>导入SQL：sql/ry_config_20220929.sql</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626235725038.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230626235845669.png" alt="image-20230626235845669"></p> <h4 id="_6-1-2-nacos配置"><a href="#_6-1-2-nacos配置" class="header-anchor">#</a> 6.1.2 Nacos配置</h4> <p>若依(RuoYi-Cloud) 配置中心的项目配置文件，持久化在<strong>ry-config.config_info</strong>  表中，项目启动需要将这些配置文件加载到配置中心，所以需要额外配置一下Nacos，以增加对mysql数据源的支持。</p> <p>进入nacos-server-2.2.2/conf 目录找：application.properties</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627001017623.png" alt=""></em></p> <p>修改配置</p> <div class="language-properties line-numbers-mode"><pre class="language-properties"><code><span class="token comment">## db mysql</span>
<span class="token key attr-name">spring.datasource.platform</span><span class="token punctuation">=</span><span class="token value attr-value">mysql</span>
<span class="token key attr-name">db.num</span><span class="token punctuation">=</span><span class="token value attr-value">1</span>
<span class="token key attr-name">db.url.0</span><span class="token punctuation">=</span><span class="token value attr-value">jdbc:mysql://localhost:3306/ry-config?characterEncoding=utf8&amp;connectTimeout=1000&amp;socketTimeout=3000&amp;autoReconnect=true&amp;useUnicode=true&amp;useSSL=false&amp;serverTimezone=UTC</span>
<span class="token key attr-name">db.user</span><span class="token punctuation">=</span><span class="token value attr-value">数据库账号</span>
<span class="token key attr-name">db.password</span><span class="token punctuation">=</span><span class="token value attr-value">数据库密码</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627001136980.png" alt=""></em></p> <h4 id="_6-1-3-项目配置文件"><a href="#_6-1-3-项目配置文件" class="header-anchor">#</a> 6.1.3 项目配置文件</h4> <p>Nacos配置好之后，启动成功后访问：http://localhost:8848/nacos   账号/密码  nacos/nacos</p> <p>修改下面画红线的服务配置文件</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627002316239.png" alt=""></p> <p>主要改动：</p> <p>Redis 的ip，端口，密码</p> <p>MySQL ip，端口，账号，密码，数据库等。</p> <p>比如：</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627002521102.png" alt=""></p> <h3 id="_6-2-后端启动"><a href="#_6-2-后端启动" class="header-anchor">#</a> 6.2 后端启动</h3> <p>打开项目，执行XxxxApplication的启动类（启动没有先后顺序）</p> <ul><li><strong>RuoYiGatewayApplication</strong> （网关模块 必须）</li> <li><strong>RuoYiAuthApplication</strong> （认证模块 必须）</li> <li><strong>RuoYiSystemApplication</strong> （系统模块 必须）</li> <li>RuoYiMonitorApplication （监控中心 可选）</li> <li>RuoYiGenApplication （代码生成 可选）</li> <li>RuoYiJobApplication （定时任务 可选）</li> <li>RuoYFileApplication （文件服务 可选）</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627002804791.png" alt=""></p> <p>加粗的启动即可。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627003033653.png" alt=""></p> <h3 id="_6-3-前端配置与启动"><a href="#_6-3-前端配置与启动" class="header-anchor">#</a> 6.3 前端配置与启动</h3> <p>若依(RuoYi-Cloud) 项目前端跟后端是保存在同一个目录夹的。</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627003152676.png" alt=""></em></p> <p>先进入这个目录，然后使用前端编辑工具打开即可，这里使用Visual Studio Code 打开</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627003442203.png" alt=""></p> <p>进入vscode之后，打开项目README.md文件</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627003552149.png" alt=""></p> <p>打开vscode 的终端，执行上面命令</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627003631614.png" alt=""></p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627004845629.png" alt=""></em></p> <h3 id="_6-4-访问"><a href="#_6-4-访问" class="header-anchor">#</a> 6.4 访问</h3> <p>当后端，前端都启动成功之后，若依(RuoYi-Cloud) 项目就算运行成功啦。</p> <p>访问地址：http://localhost/</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627005030844.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627005050272.png" alt=""></p> <h2 id="七、模块解读"><a href="#七、模块解读" class="header-anchor">#</a> 七、模块解读</h2> <p>项目解读可以说分为2部分： 1&gt;项目结构解读(静态解读)   2&gt;业务模块解读(动态解读)</p> <p>前面种种都属于项目结构范畴，解下来就是业务模块解读，这里选择鉴权，网关，代码生成器3个核心模块讲解若依(RuoYi-Cloud)脚手架的使用。</p> <h3 id="_7-1-解读技巧"><a href="#_7-1-解读技巧" class="header-anchor">#</a> 7.1 解读技巧</h3> <p>只要是Java Web项目，流程主干线永远不变： <strong>发起请求---处理请求----响应请求</strong></p> <p>找一个业务逻辑相对简单的模块，围绕主线去追踪即可。根据以往的经验，请求到响应大体流程图如下：</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627024232636.png" alt=""></p> <p>把上面流程具体化之后就是：</p> <ul><li><p>前端</p> <p>客户端如何发起请求（关注路径/方式/参数），一般使用浏览器的F12查看</p></li> <li><p>后端</p> <p>接口接收请求，处理请求，响应请求。(关注：单个服务操作/多服务协同操作)，一般追踪请求流程。</p></li></ul> <p>​       简单流程：网关---过滤器---拦截器--微服务(请求处理)</p> <p>​       复杂流程：网关---上游过滤器---上游拦截器--上游微服务(处理)-----下游过滤器---下游拦截器--下游微服务(处理)</p> <h3 id="_7-2-请求闭环"><a href="#_7-2-请求闭环" class="header-anchor">#</a> 7.2 请求闭环</h3> <p>这里结合上面主线，走一个完整的请求闭环，以获取登录验证码获取为例子。</p> <h4 id="_7-2-1-前端"><a href="#_7-2-1-前端" class="header-anchor">#</a> 7.2.1 前端</h4> <p>项目进入第一个页面是登录页面</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627025010494.png" alt=""></p> <p>浏览器F12，查看到第一个接口：http://localhost/dev-api/code</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627025050988.png" alt=""></p> <p>**localhost：**前端项目启动默认访问ip， 为本地</p> <p>**端口：**没有端口，默认端口为80</p> <p>**dev-api：**若依框架约定的开发环境使用上下文，可以在.env.development中配置</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627082907769.png" alt=""></p> <p>**code：**请求路径</p> <p>完整的：http://locallhost:80/dev-api/code 是由下面异步请求发起的</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627083244710.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627083540269.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627083650541.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627083726062.png" alt=""></p> <p>当前端发起请求后，就到后端接收请求处理，处理请求，与响应请求啦。</p> <h4 id="_7-2-2-后端"><a href="#_7-2-2-后端" class="header-anchor">#</a> 7.2.2 后端</h4> <p>前端发起请求，后端接收请求，那请求最先去到哪呢？</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/up-82e9722ecb846786405a904bafcf19f73f3.png" alt="ruoyi-cloud"></p> <p>看若依(RuoYi-Cloud)框架的架构图，请求最先进入的网关。当然也可以通过前端代理服务配置定位到请求会转发到网关服务。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627085133404.png" alt=""></p> <p>当确认请求入口之后，只需快速定位ruoyi-gateway即可。</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627084350851.png" alt=""></em></p> <p>此时还存在一个问题，网关哪个类处理/code请求？</p> <p>如果有WebFlux编程经验，大体能猜到RouterFunctionConfiguration类</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">RouterFunctionConfiguration</span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">ValidateCodeHandler</span> validateCodeHandler<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@SuppressWarnings</span><span class="token punctuation">(</span><span class="token string">&quot;rawtypes&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">RouterFunction</span> <span class="token function">routerFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token class-name">RouterFunctions</span><span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span>
                <span class="token class-name">RequestPredicates</span><span class="token punctuation">.</span><span class="token function">GET</span><span class="token punctuation">(</span><span class="token string">&quot;/code&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">and</span><span class="token punctuation">(</span><span class="token class-name">RequestPredicates</span><span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token class-name">MediaType</span><span class="token punctuation">.</span><span class="token constant">TEXT_PLAIN</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                validateCodeHandler<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>RouterFunction 是 Spring WebFlux 中定义路由的函数式编程方式。</p> <p>在 Spring WebFlux 中，我们可以使用 <code>RouterFunction</code> 来定义路由规则，将请求映射到相应的处理器函数上。</p> <p>上面代码意思是前端发过来/code由validateCodeHandler 来处理</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ValidateCodeHandler</span> <span class="token keyword">implements</span> <span class="token class-name">HandlerFunction</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ServerResponse</span><span class="token punctuation">&gt;</span></span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">ValidateCodeService</span> validateCodeService<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">Mono</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ServerResponse</span><span class="token punctuation">&gt;</span></span> <span class="token function">handle</span><span class="token punctuation">(</span><span class="token class-name">ServerRequest</span> serverRequest<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token class-name">AjaxResult</span> ajax<span class="token punctuation">;</span>
        <span class="token keyword">try</span>
        <span class="token punctuation">{</span>
            <span class="token comment">//构建验证码，封装成AjaxResult对象</span>
            ajax <span class="token operator">=</span> validateCodeService<span class="token punctuation">.</span><span class="token function">createCaptcha</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">CaptchaException</span> <span class="token operator">|</span> <span class="token class-name">IOException</span> e<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token class-name">Mono</span><span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token class-name">ServerResponse</span><span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation">.</span><span class="token constant">OK</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">body</span><span class="token punctuation">(</span><span class="token class-name">BodyInserters</span><span class="token punctuation">.</span><span class="token function">fromValue</span><span class="token punctuation">(</span>ajax<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">AjaxResult</span> <span class="token function">createCaptcha</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span><span class="token punctuation">,</span> <span class="token class-name">CaptchaException</span>
<span class="token punctuation">{</span>
    <span class="token class-name">AjaxResult</span> ajax <span class="token operator">=</span> <span class="token class-name">AjaxResult</span><span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">boolean</span> captchaEnabled <span class="token operator">=</span> captchaProperties<span class="token punctuation">.</span><span class="token function">getEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    ajax<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;captchaEnabled&quot;</span><span class="token punctuation">,</span> captchaEnabled<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    ajax<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;uuid&quot;</span><span class="token punctuation">,</span> uuid<span class="token punctuation">)</span><span class="token punctuation">;</span>
    ajax<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;img&quot;</span><span class="token punctuation">,</span> <span class="token class-name">Base64</span><span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span><span class="token function">toByteArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> ajax<span class="token punctuation">;</span>
        
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>最终将生成的验证码封装在AjaxResult 响应回客户端。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627085805996.png" alt=""></p> <p>那如果说没有Spring WebFlux经验怎么办？很简单，使用idea 搜/code 字符，然后借助ChatGPT猜测代码啥意思</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627090056877.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627090235025.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627090412040.png" alt=""></p> <p>到这，一个完整请求闭环就完成了，后续其他请求便是同理可得。</p> <h3 id="_7-3-网关模块"><a href="#_7-3-网关模块" class="header-anchor">#</a> 7.3 网关模块</h3> <p>网关为项目入口，若依(RuoYi-Cloud)项目入口结构可以简化为这样</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627115900446.png" alt=""></p> <p>在ruoyi-gateway网关微服务中配置了所有微服务路由映射</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627102732901.png" alt=""></p> <div class="language-yaml line-numbers-mode"><pre class="language-yaml"><code><span class="token key atrule">spring</span><span class="token punctuation">:</span>
  <span class="token key atrule">cloud</span><span class="token punctuation">:</span>
    <span class="token key atrule">gateway</span><span class="token punctuation">:</span>
      <span class="token key atrule">discovery</span><span class="token punctuation">:</span>
        <span class="token key atrule">locator</span><span class="token punctuation">:</span>
          <span class="token key atrule">lowerCaseServiceId</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
          <span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
      <span class="token key atrule">routes</span><span class="token punctuation">:</span>
        <span class="token comment">## 认证中心</span>
        <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> ruoyi<span class="token punctuation">-</span>auth
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> lb<span class="token punctuation">:</span>//ruoyi<span class="token punctuation">-</span>auth
          <span class="token key atrule">predicates</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> Path=/auth/<span class="token important">**</span>
          <span class="token key atrule">filters</span><span class="token punctuation">:</span>
            <span class="token comment">## 验证码处理</span>
            <span class="token punctuation">-</span> CacheRequestFilter
            <span class="token punctuation">-</span> ValidateCodeFilter
            <span class="token punctuation">-</span> StripPrefix=1
        <span class="token comment">## 代码生成</span>
        <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> ruoyi<span class="token punctuation">-</span>gen
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> lb<span class="token punctuation">:</span>//ruoyi<span class="token punctuation">-</span>gen
          <span class="token key atrule">predicates</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> Path=/code/<span class="token important">**</span>
          <span class="token key atrule">filters</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> StripPrefix=1
        <span class="token comment">## 定时任务</span>
        <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> ruoyi<span class="token punctuation">-</span>job
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> lb<span class="token punctuation">:</span>//ruoyi<span class="token punctuation">-</span>job
          <span class="token key atrule">predicates</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> Path=/schedule/<span class="token important">**</span>
          <span class="token key atrule">filters</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> StripPrefix=1
        <span class="token comment">## 系统模块</span>
        <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> ruoyi<span class="token punctuation">-</span>system
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> lb<span class="token punctuation">:</span>//ruoyi<span class="token punctuation">-</span>system
          <span class="token key atrule">predicates</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> Path=/system/<span class="token important">**</span>
          <span class="token key atrule">filters</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> StripPrefix=1
        <span class="token comment">## 文件服务</span>
        <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> ruoyi<span class="token punctuation">-</span>file
          <span class="token key atrule">uri</span><span class="token punctuation">:</span> lb<span class="token punctuation">:</span>//ruoyi<span class="token punctuation">-</span>file
          <span class="token key atrule">predicates</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> Path=/file/<span class="token important">**</span>
          <span class="token key atrule">filters</span><span class="token punctuation">:</span>
            <span class="token punctuation">-</span> StripPrefix=1

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br></div></div><p>前端发起所有请都统一经过网关，再借由网关路由统一转发。</p> <p>访问ruoyi-file微服务路径规则：   http://localhost:80/dev-api/file/**</p> <p>访问ruoyi-gen微服务路径规则：   http://localhost:80/dev-api/code/**</p> <p>访问ruoyi-job微服务路径规则：   http://localhost:80/dev-api/schedule/**</p> <p>访问ruoyi-system微服务路径规则：   http://localhost:80/dev-api/system/**</p> <p>访问ruoyi-auth微服务路径规则：   http://localhost:80/dev-api/auth/**</p> <h3 id="_7-4-鉴权模块"><a href="#_7-4-鉴权模块" class="header-anchor">#</a> 7.4 鉴权模块</h3> <p>若依(RuoYi-Cloud)鉴权模块涉及到这几个组件</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627120634170.png" alt=""></em></p> <p>若依(RuoYi-Cloud)框架登录鉴权有2种模式：</p> <p>外部鉴权：客户端访问服务端(微服务)，以JWT令牌为判断依据，有且合法放行，没有或不合法拒绝</p> <p>内部鉴权：上游微服务访问下游微服务，以请求头标记：<strong>from-source=inner</strong>有无位依据，有放行，没有拒绝</p> <h4 id="_7-4-1-外部鉴权"><a href="#_7-4-1-外部鉴权" class="header-anchor">#</a> 7.4.1 外部鉴权</h4> <h5 id="_7-4-1-1-步骤1-jwt获取"><a href="#_7-4-1-1-步骤1-jwt获取" class="header-anchor">#</a> 7.4.1.1 <strong>步骤1：JWT获取</strong></h5> <p>登录页面点击登录发起：http://localhost/dev-api/auth/login 请求</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627102627157.png" alt=""></p> <p>请求中auth前缀为网关配置ry-auth服务路由映射</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627102732901.png" alt="image-20230627102732901"></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627102800679.png" alt=""></p> <p>借助网格路由，进入ry-auth微服务，TokenController请求处理类</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TokenController</span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;login&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">R</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> <span class="token class-name">LoginBody</span> form<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// 用户登录</span>
        <span class="token class-name">LoginUser</span> userInfo <span class="token operator">=</span> sysLoginService<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>form<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> form<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取登录token</span>
        <span class="token keyword">return</span> <span class="token class-name">R</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span>tokenService<span class="token punctuation">.</span><span class="token function">createToken</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>    
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code>    <span class="token comment">/**
     * 创建令牌
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span> <span class="token function">createToken</span><span class="token punctuation">(</span><span class="token class-name">LoginUser</span> loginUser<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token class-name">String</span> token <span class="token operator">=</span> <span class="token class-name">IdUtils</span><span class="token punctuation">.</span><span class="token function">fastUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Long</span> userId <span class="token operator">=</span> loginUser<span class="token punctuation">.</span><span class="token function">getSysUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getUserId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> userName <span class="token operator">=</span> loginUser<span class="token punctuation">.</span><span class="token function">getSysUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getUserName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        loginUser<span class="token punctuation">.</span><span class="token function">setToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        loginUser<span class="token punctuation">.</span><span class="token function">setUserid</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
        loginUser<span class="token punctuation">.</span><span class="token function">setUsername</span><span class="token punctuation">(</span>userName<span class="token punctuation">)</span><span class="token punctuation">;</span>
        loginUser<span class="token punctuation">.</span><span class="token function">setIpaddr</span><span class="token punctuation">(</span><span class="token class-name">IpUtils</span><span class="token punctuation">.</span><span class="token function">getIpAddr</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">refreshToken</span><span class="token punctuation">(</span>loginUser<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">//redis缓存令牌</span>

        <span class="token comment">// Jwt存储信息</span>
        <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span> claimsMap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        claimsMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">USER_KEY</span><span class="token punctuation">,</span> token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        claimsMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">DETAILS_USER_ID</span><span class="token punctuation">,</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
        claimsMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">DETAILS_USERNAME</span><span class="token punctuation">,</span> userName<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 接口返回信息</span>
        <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span> rspMap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        rspMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;access_token&quot;</span><span class="token punctuation">,</span> <span class="token class-name">JwtUtils</span><span class="token punctuation">.</span><span class="token function">createToken</span><span class="token punctuation">(</span>claimsMap<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        rspMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;expires_in&quot;</span><span class="token punctuation">,</span> expireTime<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> rspMap<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>响应返回：</p> <p><img src="images/!%5B%5D(https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627103210377.png)" alt=""></p> <h5 id="_7-4-1-2-步骤2-jwt鉴权"><a href="#_7-4-1-2-步骤2-jwt鉴权" class="header-anchor">#</a> 7.4.1.2 <strong>步骤2：JWT鉴权</strong></h5> <p>当客户登录成功之后，后续请求进入网关，网关转发到对应的微服务，该微服务会引用：ruoyi-common-security 鉴权模块，请求进来后，切面判断请求持有的JWT令牌，有且合法放行，没有或不合法拒绝</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627103917494.png" alt=""></p> <h5 id="_7-4-1-3-步骤3-jwt鉴权实现"><a href="#_7-4-1-3-步骤3-jwt鉴权实现" class="header-anchor">#</a> 7.4.1.3 <strong>步骤3：JWT鉴权实现</strong></h5> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Aspect</span>
<span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PreAuthorizeAspect</span>
<span class="token punctuation">{</span>
    <span class="token comment">/**
     * 构建
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">PreAuthorizeAspect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 定义AOP签名 (切入所有使用鉴权注解的方法)
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> <span class="token constant">POINTCUT_SIGN</span> <span class="token operator">=</span> <span class="token string">&quot; @annotation(com.ruoyi.common.security.annotation.RequiresLogin) || &quot;</span>
            <span class="token operator">+</span> <span class="token string">&quot;@annotation(com.ruoyi.common.security.annotation.RequiresPermissions) || &quot;</span>
            <span class="token operator">+</span> <span class="token string">&quot;@annotation(com.ruoyi.common.security.annotation.RequiresRoles)&quot;</span><span class="token punctuation">;</span>

    <span class="token comment">/**
     * 声明AOP签名
     */</span>
    <span class="token annotation punctuation">@Pointcut</span><span class="token punctuation">(</span><span class="token constant">POINTCUT_SIGN</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">pointcut</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 环绕切入
     * 
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */</span>
    <span class="token annotation punctuation">@Around</span><span class="token punctuation">(</span><span class="token string">&quot;pointcut()&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">around</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> joinPoint<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// 注解鉴权</span>
        <span class="token class-name">MethodSignature</span> signature <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">MethodSignature</span><span class="token punctuation">)</span> joinPoint<span class="token punctuation">.</span><span class="token function">getSignature</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">checkMethodAnnotation</span><span class="token punctuation">(</span>signature<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span>
        <span class="token punctuation">{</span>
            <span class="token comment">// 执行原有逻辑</span>
            <span class="token class-name">Object</span> obj <span class="token operator">=</span> joinPoint<span class="token punctuation">.</span><span class="token function">proceed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> obj<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> e<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> e<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 对一个Method对象进行注解检查
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">checkMethodAnnotation</span><span class="token punctuation">(</span><span class="token class-name">Method</span> method<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// 校验 @RequiresLogin 注解</span>
        <span class="token class-name">RequiresLogin</span> requiresLogin <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">getAnnotation</span><span class="token punctuation">(</span><span class="token class-name">RequiresLogin</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>requiresLogin <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token class-name">AuthUtil</span><span class="token punctuation">.</span><span class="token function">checkLogin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 校验 @RequiresRoles 注解</span>
        <span class="token class-name">RequiresRoles</span> requiresRoles <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">getAnnotation</span><span class="token punctuation">(</span><span class="token class-name">RequiresRoles</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>requiresRoles <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token class-name">AuthUtil</span><span class="token punctuation">.</span><span class="token function">checkRole</span><span class="token punctuation">(</span>requiresRoles<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 校验 @RequiresPermissions 注解</span>
        <span class="token class-name">RequiresPermissions</span> requiresPermissions <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">getAnnotation</span><span class="token punctuation">(</span><span class="token class-name">RequiresPermissions</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>requiresPermissions <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token class-name">AuthUtil</span><span class="token punctuation">.</span><span class="token function">checkPermi</span><span class="token punctuation">(</span>requiresPermissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br></div></div><p>阅读上面的切面代码，最终得出</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627112200912.png" alt=""></p> <p>只要接口方法只要贴有上面3个注解，都需要进行外部鉴权。比如：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">/**
* 获取用户列表
*/</span>
<span class="token annotation punctuation">@RequiresPermissions</span><span class="token punctuation">(</span><span class="token string">&quot;system:user:list&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/list&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">TableDataInfo</span> <span class="token function">list</span><span class="token punctuation">(</span><span class="token class-name">SysUser</span> user<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token function">startPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">SysUser</span><span class="token punctuation">&gt;</span></span> list <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">selectUserList</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">getDataTable</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="_7-4-2-内部鉴权"><a href="#_7-4-2-内部鉴权" class="header-anchor">#</a> 7.4.2 内部鉴权</h4> <p>内部鉴权是微服务与微服务间鉴权，发生在上游微服务访问下游微服务，以请求头标记：<strong>from-source=inner</strong>有无位依据，有放行，没有拒绝，其目的是实现网络隔离。</p> <p>来自网关请求，以JWT进行鉴权，来自内部远程调用请求，以<strong>from-source=inner</strong>进行鉴权，其他非法请求直接拒绝。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627104552698.png" alt=""></p> <p>还是以ry-auth微服务的TokenController类的登录方法为案例</p> <h5 id="_7-4-2-1-步骤1-远程调用过程"><a href="#_7-4-2-1-步骤1-远程调用过程" class="header-anchor">#</a> 7.4.2.1 <strong>步骤1：远程调用过程</strong></h5> <p>登录请求，先到TokenController类login方法</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TokenController</span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">TokenService</span> tokenService<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">SysLoginService</span> sysLoginService<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;login&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">R</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> <span class="token class-name">LoginBody</span> form<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// 用户登录</span>
        <span class="token class-name">LoginUser</span> userInfo <span class="token operator">=</span> sysLoginService<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>form<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> form<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取登录token</span>
        <span class="token keyword">return</span> <span class="token class-name">R</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span>tokenService<span class="token punctuation">.</span><span class="token function">createToken</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>login方法中用到：SysLoginService接口login逻辑</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token class-name">SysLoginService</span> sysLoginService<span class="token punctuation">;</span>
sysLoginService<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>form<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> form<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>观察SysLoginService类，里面引用了接口：RemoteUserService</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SysLoginService</span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">RemoteUserService</span> remoteUserService<span class="token punctuation">;</span>

    <span class="token comment">/**
     * 登录
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">LoginUser</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token class-name">String</span> username<span class="token punctuation">,</span> <span class="token class-name">String</span> password<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        <span class="token comment">// 查询用户信息</span>
        <span class="token class-name">R</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">LoginUser</span><span class="token punctuation">&gt;</span></span> userResult <span class="token operator">=</span> remoteUserService<span class="token punctuation">.</span><span class="token function">getUserInfo</span><span class="token punctuation">(</span>username<span class="token punctuation">,</span> <span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">INNER</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
       
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>观察RemoteUserService接口所在位置，明显与TokenController/SysLoginService不在同一微服务。</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627105220746.png" alt=""></em></p> <p>RemoteUserService 属于ry-system微服务，而TokenController类属于ry-auth微服务，那么此处的remoteUserService.getUserInfo为远程调用。</p> <blockquote><p>一个问题：既然为远程调用，跟普通接口调用有啥区别？</p></blockquote> <p><strong>定义区别：</strong></p> <p>使用feign组件，定义远程接口</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@FeignClient</span><span class="token punctuation">(</span>contextId <span class="token operator">=</span> <span class="token string">&quot;remoteUserService&quot;</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token class-name">ServiceNameConstants</span><span class="token punctuation">.</span><span class="token constant">SYSTEM_SERVICE</span><span class="token punctuation">,</span> fallbackFactory <span class="token operator">=</span> <span class="token class-name">RemoteUserFallbackFactory</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">RemoteUserService</span>
<span class="token punctuation">{</span>
    <span class="token comment">/**
     * 通过用户名查询用户信息
     *
     * @param username 用户名
     * @param source 请求来源
     * @return 结果
     */</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/user/info/{username}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">R</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">LoginUser</span><span class="token punctuation">&gt;</span></span> <span class="token function">getUserInfo</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span> <span class="token class-name">String</span> username<span class="token punctuation">,</span> <span class="token annotation punctuation">@RequestHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">FROM_SOURCE</span><span class="token punctuation">)</span> <span class="token class-name">String</span> source<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>接口定义，除了正常的username参数之外，多了一个请求头</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RequestHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">FROM_SOURCE</span><span class="token punctuation">)</span> <span class="token class-name">String</span> source
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><strong>调用区别：</strong></p> <p>使用Feign组件发起远程接口调用，需要多传一个<strong>SecurityConstants.INNER</strong> 参数</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>remoteUserService<span class="token punctuation">.</span><span class="token function">getUserInfo</span><span class="token punctuation">(</span>username<span class="token punctuation">,</span> <span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">INNER</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>这是为何？</p> <p><strong>SecurityConstants.INNER</strong>为内部微服务间远程调用请求头标识，上游微服务调用时，添加该标识的请求头，下游微服务接收请求前，进行请求头校验。</p> <p>即：</p> <p><strong>定义是指定请求头key：SecurityConstants.FROM_SOURCE</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token function">getUserInfo</span><span class="token punctuation">(</span>
      <span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span> <span class="token class-name">String</span> username<span class="token punctuation">,</span>
      <span class="token annotation punctuation">@RequestHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">FROM_SOURCE</span><span class="token punctuation">)</span> <span class="token class-name">String</span> source<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>调用时，指定请求头value：<strong>SecurityConstants.INNER</strong></p> <div class="language-java line-numbers-mode"><pre class="language-java"><code>remoteUserService<span class="token punctuation">.</span><span class="token function">getUserInfo</span><span class="token punctuation">(</span>username<span class="token punctuation">,</span> <span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">INNER</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>最终合并</p> <p><strong>SecurityConstants.FROM_SOURCE = SecurityConstants.INNER</strong></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>from-source = inner
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h5 id="_7-4-2-2-步骤2-远程正式调用"><a href="#_7-4-2-2-步骤2-远程正式调用" class="header-anchor">#</a> 7.4.2.2 <strong>步骤2：远程正式调用</strong></h5> <p>上面定义的远程接口，最终通过feign方式调用到ruoyi-system微服务SysUserController类的info接口</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627110341990.png" alt=""></p> <p>SysUserController类的info接口</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/user&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SysUserController</span> <span class="token keyword">extends</span> <span class="token class-name">BaseController</span>
<span class="token punctuation">{</span>    <span class="token comment">/**
     * 获取当前用户信息
     */</span>
    <span class="token annotation punctuation">@InnerAuth</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/info/{username}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">R</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">LoginUser</span><span class="token punctuation">&gt;</span></span> <span class="token function">info</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span> <span class="token class-name">String</span> username<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token class-name">SysUser</span> sysUser <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">selectUserByUserName</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token class-name">R</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token string">&quot;用户名或密码错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 角色集合</span>
        <span class="token class-name">Set</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> roles <span class="token operator">=</span> permissionService<span class="token punctuation">.</span><span class="token function">getRolePermission</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 权限集合</span>
        <span class="token class-name">Set</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> permissions <span class="token operator">=</span> permissionService<span class="token punctuation">.</span><span class="token function">getMenuPermission</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">LoginUser</span> sysUserVo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LoginUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        sysUserVo<span class="token punctuation">.</span><span class="token function">setSysUser</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
        sysUserVo<span class="token punctuation">.</span><span class="token function">setRoles</span><span class="token punctuation">(</span>roles<span class="token punctuation">)</span><span class="token punctuation">;</span>
        sysUserVo<span class="token punctuation">.</span><span class="token function">setPermissions</span><span class="token punctuation">(</span>permissions<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token class-name">R</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span>sysUserVo<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>    
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>这里留意，info方法上面有个**@InnerAuth** 注解，表示当前info方法为远程调用方法，需要进行远程校验，也即：内部鉴权。</p> <h5 id="_7-4-2-3-步骤3-内部鉴权"><a href="#_7-4-2-3-步骤3-内部鉴权" class="header-anchor">#</a> 7.4.2.3 <strong>步骤3：内部鉴权</strong></h5> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Aspect</span>
<span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InnerAuthAspect</span> <span class="token keyword">implements</span> <span class="token class-name">Ordered</span>
<span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Around</span><span class="token punctuation">(</span><span class="token string">&quot;@annotation(innerAuth)&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">innerAround</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> point<span class="token punctuation">,</span> <span class="token class-name">InnerAuth</span> innerAuth<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span>
    <span class="token punctuation">{</span>
        <span class="token class-name">String</span> source <span class="token operator">=</span> <span class="token class-name">ServletUtils</span><span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">FROM_SOURCE</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 内部请求验证</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">INNER</span><span class="token punctuation">,</span> source<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InnerAuthException</span><span class="token punctuation">(</span><span class="token string">&quot;没有内部访问权限，不允许访问&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token class-name">String</span> userid <span class="token operator">=</span> <span class="token class-name">ServletUtils</span><span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">DETAILS_USER_ID</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> username <span class="token operator">=</span> <span class="token class-name">ServletUtils</span><span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token class-name">SecurityConstants</span><span class="token punctuation">.</span><span class="token constant">DETAILS_USERNAME</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 用户信息验证</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>innerAuth<span class="token punctuation">.</span><span class="token function">isUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>userid<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InnerAuthException</span><span class="token punctuation">(</span><span class="token string">&quot;没有设置用户信息，不允许访问 &quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> point<span class="token punctuation">.</span><span class="token function">proceed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 确保在权限认证aop执行前执行
     */</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getOrder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token class-name">Ordered</span><span class="token punctuation">.</span><span class="token constant">HIGHEST_PRECEDENCE</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br></div></div><p>阅读上面的切面代码，发起切面是切入点事贴有@InnerAuth接口方法。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627112424706.png" alt=""></p> <h3 id="_7-5-代码生成模块"><a href="#_7-5-代码生成模块" class="header-anchor">#</a> 7.5 代码生成模块</h3> <p>若依(RuoYi-Cloud)代码生成模块是一个简单模块，功能顾名思义，用于构建若依体系的代码。</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627121400569.png" alt=""></em></p> <p>启动后，访问页面：</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627121447698.png" alt=""></p> <p>这里演示一下代码生成器使用过程。</p> <h4 id="_7-5-1-步骤1-创建表"><a href="#_7-5-1-步骤1-创建表" class="header-anchor">#</a> 7.5.1 步骤1：创建表</h4> <p>在ry-cloud库中创建一个Employee表</p> <div class="language-sql line-numbers-mode"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> <span class="token identifier"><span class="token punctuation">`</span>sys_employee<span class="token punctuation">`</span></span> <span class="token punctuation">(</span>
  <span class="token identifier"><span class="token punctuation">`</span>id<span class="token punctuation">`</span></span> <span class="token keyword">bigint</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">AUTO_INCREMENT</span> <span class="token keyword">COMMENT</span> <span class="token string">'主键'</span><span class="token punctuation">,</span>
  <span class="token identifier"><span class="token punctuation">`</span>name<span class="token punctuation">`</span></span> <span class="token keyword">varchar</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">)</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span> <span class="token keyword">COMMENT</span> <span class="token string">'名称'</span><span class="token punctuation">,</span>
  <span class="token identifier"><span class="token punctuation">`</span>age<span class="token punctuation">`</span></span> <span class="token keyword">int</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span> <span class="token keyword">COMMENT</span> <span class="token string">'年龄'</span><span class="token punctuation">,</span>
  <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span> <span class="token punctuation">(</span><span class="token identifier"><span class="token punctuation">`</span>id<span class="token punctuation">`</span></span><span class="token punctuation">)</span>
<span class="token punctuation">)</span> <span class="token keyword">ENGINE</span><span class="token operator">=</span><span class="token keyword">InnoDB</span>  <span class="token keyword">COMMENT</span><span class="token operator">=</span><span class="token string">'员工表'</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h4 id="_7-5-2-步骤2-导入新建表"><a href="#_7-5-2-步骤2-导入新建表" class="header-anchor">#</a> 7.5.2 步骤2：导入新建表</h4> <p>在代码生成界面导入新建表</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627122048884.png" alt=""></p> <h4 id="_7-5-3-步骤3-定制代码信息"><a href="#_7-5-3-步骤3-定制代码信息" class="header-anchor">#</a> 7.5.3 <strong>步骤3：定制代码信息</strong></h4> <h5 id="_7-5-3-1-基本信息"><a href="#_7-5-3-1-基本信息" class="header-anchor">#</a> 7.5.3.1 <strong>基本信息</strong></h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627122210064.png" alt=""></p> <h5 id="_7-5-3-2-字段信息"><a href="#_7-5-3-2-字段信息" class="header-anchor">#</a> 7.5.3.2 <strong>字段信息</strong></h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627122308878.png" alt=""></p> <p><strong>字段列名</strong>：表中列的名称</p> <p><strong>字段描述</strong>：生成实体类属性注释</p> <p><strong>物理类型</strong>：表中列的类型</p> <p><strong>Java类型</strong>：生成实体类属性变量类型</p> <p><strong>Java属性</strong>：生成实体类属性名</p> <p><strong>插入</strong>：定义添加操作模态框表单控件，选中表示模态框有这个输入空间</p> <p><strong>编辑</strong>：定义编辑操作模态框表单控件，选中表示模态框有这个输入空间</p> <p><strong>列表</strong>：表中数据在列表时，该列数据是否显示，选中为要显示</p> <p><strong>查询</strong>：该列是否作为列表的查询条件，选中为需要作为查询条件</p> <p><strong>查询方式</strong>：作为查询条件时，使用匹配方式</p> <p><strong>显示类型</strong>：查询条件输入类型</p> <p><strong>字典类型</strong>：查询条件显示类型如果是下拉框，使用字典类型，实现下拉选择</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627123010822.png" alt=""></em></p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627123031957.png" alt=""></em></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627122956279.png" alt=""></p> <h5 id="_7-5-3-3-生成信息"><a href="#_7-5-3-3-生成信息" class="header-anchor">#</a> 7.5.3.3 生成信息</h5> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627123327479.png" alt=""></p> <p>生成模板：一般不动，以单表操作为主</p> <p>生成包路径：指定当前代码生成根包路径</p> <p>生成模块名：该功能所属模块，落地到代码就是所在微服务名称，ruoyi-gateway配置的路由映射路径名</p> <p>生成业务名：该功能英文名，落地到代码就是controller中操作资源名， 比如：/employee</p> <p>生成功能名：该功能中文名称</p> <p>上级菜单：该功能页面展示菜单连接挂载在哪个上级菜单。</p> <h5 id="_7-5-3-4-预览"><a href="#_7-5-3-4-预览" class="header-anchor">#</a> 7.5.3.4 预览</h5> <p>配置上面各种信息成功之后，可以点击预览，根据需要微调</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124027839.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124112142.png" alt=""></p> <h5 id="_7-5-3-5-生成代码"><a href="#_7-5-3-5-生成代码" class="header-anchor">#</a> 7.5.3.5 生成代码</h5> <p>确定无误之后，直接点生成代码</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124158525.png" alt=""></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124216989.png" alt=""></p> <h4 id="_7-5-4-步骤4-使用代码"><a href="#_7-5-4-步骤4-使用代码" class="header-anchor">#</a> 7.5.4 步骤4：使用代码</h4> <p>压缩包解压得到几个文件：</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627125016476.png" alt=""></em></p> <h5 id="_7-5-4-1-employeemenu-sql"><a href="#_7-5-4-1-employeemenu-sql" class="header-anchor">#</a> 7.5.4.1 <strong>employeeMenu.sql</strong></h5> <p>涉及要添加的菜单，菜单权限，在navicat中执行即可。</p> <div class="language-sql line-numbers-mode"><pre class="language-sql"><code><span class="token comment">-- 菜单 SQL</span>
<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工'</span><span class="token punctuation">,</span> <span class="token string">'1'</span><span class="token punctuation">,</span> <span class="token string">'1'</span><span class="token punctuation">,</span> <span class="token string">'employee'</span><span class="token punctuation">,</span> <span class="token string">'system/employee/index'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'C'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:list'</span><span class="token punctuation">,</span> <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">'员工菜单'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">-- 按钮父菜单ID</span>
<span class="token keyword">SELECT</span> <span class="token variable">@parentId</span> :<span class="token operator">=</span> LAST_INSERT_ID<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">-- 按钮 SQL</span>
<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工查询'</span><span class="token punctuation">,</span> <span class="token variable">@parentId</span><span class="token punctuation">,</span> <span class="token string">'1'</span><span class="token punctuation">,</span>  <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'F'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:query'</span><span class="token punctuation">,</span>        <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工新增'</span><span class="token punctuation">,</span> <span class="token variable">@parentId</span><span class="token punctuation">,</span> <span class="token string">'2'</span><span class="token punctuation">,</span>  <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'F'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:add'</span><span class="token punctuation">,</span>          <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工修改'</span><span class="token punctuation">,</span> <span class="token variable">@parentId</span><span class="token punctuation">,</span> <span class="token string">'3'</span><span class="token punctuation">,</span>  <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'F'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:edit'</span><span class="token punctuation">,</span>         <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工删除'</span><span class="token punctuation">,</span> <span class="token variable">@parentId</span><span class="token punctuation">,</span> <span class="token string">'4'</span><span class="token punctuation">,</span>  <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'F'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:remove'</span><span class="token punctuation">,</span>       <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">insert</span> <span class="token keyword">into</span> sys_menu <span class="token punctuation">(</span>menu_name<span class="token punctuation">,</span> parent_id<span class="token punctuation">,</span> order_num<span class="token punctuation">,</span> path<span class="token punctuation">,</span> component<span class="token punctuation">,</span> is_frame<span class="token punctuation">,</span> is_cache<span class="token punctuation">,</span> menu_type<span class="token punctuation">,</span> visible<span class="token punctuation">,</span> <span class="token keyword">status</span><span class="token punctuation">,</span> perms<span class="token punctuation">,</span> icon<span class="token punctuation">,</span> create_by<span class="token punctuation">,</span> create_time<span class="token punctuation">,</span> update_by<span class="token punctuation">,</span> update_time<span class="token punctuation">,</span> remark<span class="token punctuation">)</span>
<span class="token keyword">values</span><span class="token punctuation">(</span><span class="token string">'员工导出'</span><span class="token punctuation">,</span> <span class="token variable">@parentId</span><span class="token punctuation">,</span> <span class="token string">'5'</span><span class="token punctuation">,</span>  <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'F'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">,</span> <span class="token string">'system:employee:export'</span><span class="token punctuation">,</span>       <span class="token string">'#'</span><span class="token punctuation">,</span> <span class="token string">'admin'</span><span class="token punctuation">,</span> sysdate<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token boolean">null</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><p>执行成功后，刷新前端项目，可以看到菜单</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124525020.png" alt=""></em></p> <h5 id="_7-5-4-2-vue"><a href="#_7-5-4-2-vue" class="header-anchor">#</a> 7.5.4.2 <strong>vue</strong></h5> <p>ruoyi-ui前端employee这个模块设计到vue页面，与js</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124648578.png" alt=""></em></p> <p>分别拷贝到项目api目录，跟views目录</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124844264.png" alt=""></em></p> <p>刷新之后，点击员工菜单，缺少后端接口</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627124922670.png" alt=""></p> <h5 id="_7-5-4-3-main"><a href="#_7-5-4-3-main" class="header-anchor">#</a> 7.5.4.3 <strong>main</strong></h5> <p>后端接口代码，将main代码拷贝到ruoyi-system  main目录中即可</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627125254678.png" alt=""></em></p> <p>然后，重启ruoyi-system服务，再访问。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627125740228.png" alt=""></p> <h2 id="八、定制微服务"><a href="#八、定制微服务" class="header-anchor">#</a> 八、定制微服务</h2> <h3 id="_8-1-需求"><a href="#_8-1-需求" class="header-anchor">#</a> 8.1 需求</h3> <p>定制微服务-ruoyi-modules-test</p> <h3 id="_8-2-代码结构"><a href="#_8-2-代码结构" class="header-anchor">#</a> 8.2 代码结构</h3> <p>对外api：ruoyi-api-test</p> <p>微服务：ruoyi-modules-test</p> <h3 id="_8-3-实现步骤"><a href="#_8-3-实现步骤" class="header-anchor">#</a> 8.3 实现步骤</h3> <h4 id="_8-3-1-步骤1-定义ruoyi-api-test"><a href="#_8-3-1-步骤1-定义ruoyi-api-test" class="header-anchor">#</a> 8.3.1 步骤1：定义ruoyi-api-test</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627130527413.png" alt=""></p> <p>导入依赖参考ruoyi-api-system</p> <p>创建包结构参考ruoyi-api-system</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627131059710.png" alt=""></p> <p>这里注意包命名规则：</p> <p>com.ruoyi-----公司域名倒写</p> <p>system------微服务名</p> <p>api------模块名</p> <h4 id="_8-3-2-步骤2-等级ruoyi-api-test依赖"><a href="#_8-3-2-步骤2-等级ruoyi-api-test依赖" class="header-anchor">#</a> 8.3.2 步骤2：等级ruoyi-api-test依赖</h4> <p>去父项目ruoyi  pom.xml文件中登记新建的api</p> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code><span class="token comment">&lt;!-- test接口 --&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>com.ruoyi<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>ruoyi-api-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>${ruoyi.version}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h4 id="_8-3-3-步骤3-定义ruoyi-modules-test"><a href="#_8-3-3-步骤3-定义ruoyi-modules-test" class="header-anchor">#</a> 8.3.3 步骤3：定义ruoyi-modules-test</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627131334808.png" alt=""></p> <p>导入依赖参考，ruoyi-system 注意要导入ruoyi-api-test依赖</p> <p>创建包结构参考ruoyi-system</p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627132033109.png" alt=""></em></p> <h4 id="_8-3-4-步骤4-定制微服务配置文件"><a href="#_8-3-4-步骤4-定制微服务配置文件" class="header-anchor">#</a> 8.3.4 步骤4：定制微服务配置文件</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627132159224.png" alt=""></p> <p>nacos克隆一份配置文件--克隆自ruoyi-system-dev.yml</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627132356925.png" alt=""></p> <h4 id="_8-3-5-步骤5-定制网关微服务路由"><a href="#_8-3-5-步骤5-定制网关微服务路由" class="header-anchor">#</a> 8.3.5 步骤5：定制网关微服务路由</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627132509241.png" alt=""></p> <p><em><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20230627132552907.png" alt=""></em></p> <p>到这，定制微服务就结束了，剩下操作就是常规crud了。</p> <h2 id="九、小结与作业"><a href="#九、小结与作业" class="header-anchor">#</a> 九、小结与作业</h2> <p>将整篇教程总结一下：若依(Ruoyi-Cloud)版本使用</p> <p><strong>启动</strong></p> <p>1&gt;官网克隆项目到idea</p> <p>2&gt;按照文档，建库，建表，配置nacos</p> <p>3&gt;准备各种环境，修改本地配置</p> <p>4&gt;前后端启动，测试。</p> <p><strong>模块解读</strong></p> <p>1&gt;网关模块，所有请求入口</p> <p>2&gt;鉴权模块，外部鉴权，内部鉴权</p> <p>3&gt;代码生成模块，先建表，再定制，后覆盖</p> <p>微服务定制</p> <p>1&gt;拷贝模仿现有api/modules</p> <p>2&gt;配置中心加配置文件</p> <p>3&gt;网关配置转发路由</p></div></div>  <div class="page-edit"><!----> <div class="tags"><a href="/tags/?tag=ruoyi" title="标签">#ruoyi</a></div> <!----></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/e4621d/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">脚手架-RuoYi-Vue 前后端分离版</div></a> <a href="/pages/9e54ff/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">Activiti7工作流讲义</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/e4621d/" class="prev">脚手架-RuoYi-Vue 前后端分离版</a></span> <span class="next"><a href="/pages/9e54ff/">Activiti7工作流讲义</a>→
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/pages/0c07b2/"><div>
            IT杂货铺
            <!----></div></a> <span class="date">03-23</span></dt></dl><dl><dd>02</dd> <dt><a href="/pages/705b35/"><div>
            人事百问
            <!----></div></a> <span class="date">03-22</span></dt></dl><dl><dd>03</dd> <dt><a href="/pages/78eb56/"><div>
            MyBatis-Plus
            <!----></div></a> <span class="date">03-12</span></dt></dl> <dl><dd></dd> <dt><a href="/archives/" class="more">更多文章&gt;</a></dt></dl></div></div></main></div> <div class="footer"><div class="icons"><a href="mailto:langfeiyes@163.com" title="发邮件" target="_blank" class="iconfont icon-youjian"></a><a href="https://github.com/langfeiyes" title="GitHub" target="_blank" class="iconfont icon-github"></a><a href="https://music.163.com/#/playlist?id=755597173" title="听音乐" target="_blank" class="iconfont icon-erji"></a></div> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2024-2024
    <span><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备18007927号-1</a></span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div> <div title="主题模式" class="button blur theme-mode-but iconfont icon-zhuti"><ul class="select-box" style="display:none;"><li class="iconfont icon-zidong">
          跟随系统
        </li><li class="iconfont icon-rijianmoshi">
          浅色模式
        </li><li class="iconfont icon-yejianmoshi">
          深色模式
        </li><li class="iconfont icon-yuedu">
          阅读模式
        </li></ul></div></div> <!----> <!----> <!----></div><div class="global-ui"><div></div></div></div>
    <script src="/assets/js/app.a2a00aa5.js" defer></script><script src="/assets/js/2.256f807a.js" defer></script><script src="/assets/js/66.799f2eb4.js" defer></script>
  </body>
</html>
